Maison > interface Web > js tutoriel > Apprenons Cookie ensemble

Apprenons Cookie ensemble

小云云
Libérer: 2018-02-09 14:35:46
original
1837 Les gens l'ont consulté

Cet article parle principalement des cookies avec tout le monde. Si vous devez comprendre les cookies en chinois, il devrait s'agir d'un petit fichier texte, inventé par Lou Monterey, l'un des fondateurs de Netscape, en 1993. J'espère que cet article pourra aider tout le monde.

Mettre en œuvre la fonction d'enregistrement de base

Nous ouvrons le site Web et parcourons le site Web. Les deux opérations les plus courantes sont l'enregistrement et la connexion, il est donc nécessaire d'explorer comment ces deux fonctions sont mises en œuvre.

Simulation locale, lors de la saisie de localhost:8080/sign_up, le navigateur initie une requête get, et le serveur vous répondsign_up.html

//服务器端代码
if (path === '/sign_up' && method === 'GET') {
    let string = fs.readFileSync('./sign_up.html', 'utf8')
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(string)
    response.end()
 }
Copier après la connexion

Plusieurs pièges dans la mise en page CSS

Lors de l'écriture sign_up.html, faites attention à quelques connaissances en CSS :

  1. Si vous souhaitez que le corps de votre page de connexion remplisse tout l'écran, modifiez-le en fonction de la taille du changements de fenêtre Si vous souhaitez changer, vous pouvez écrire

body, html{height: 100%}
//或者
body{min-height: 100%}
html{height: 100%}
//不能这么写
body, html{min-height: 100%}
Copier après la connexion

Bien sûr, en fait, vous pouvez simplement écrire

body{min-height: 100vh}
Copier après la connexion
  1. label balise C'est display: inline, et la largeur ne peut pas être définie. les éléments en ligne adapteront la largeur en fonction du contenu en ligne, donc définir la largeur des éléments en ligne n'a aucun effet. Remplacez par inline-block就可以了

Apprenons Cookie ensemble

Obtenir les données utilisateur

Comme il s'agit d'une condition d'enregistrement, nous Le premier point de préoccupation est le suivant : comment obtenons-nous les informations d'enregistrement de l'utilisateur ?

Il est très important de choisir une structure de données raisonnable pour stocker les données.

  1. Le input de chaque name peut être stocké à l'aide d'un tableau

  2. input value doit être stocké à l'aide hash, c'est-à-dire que les objets sont stockés.

  3. La routine ci-dessus sera utilisée pour toujours, la combinaison de hash+[].

//使用jq来写
let hash = {}
let $form = $('#signUpForm')
$form.on('submit', (e) => {
  e.preventDefault() //不用form表单的默认提交,而是使用我们的的ajax提交
  let need = ['email', 'password', 'password_confirmation']
  need.forEach((name) => {
  let value = $form.find(`[name=${name}]`).val()
  hash[name] = value
})
Copier après la connexion

Enfin, ce qui est stocké dans hash est

{
  'email': '...',
  'password': '...',
  'password_confirmation': '...'
}
Copier après la connexion

Jusqu'à présent, nous avons encapsulé les données de l'utilisateur dans un objet.

Cependant, avant d'envoyer le hachage en utilisant ajax, vous devez d'abord effectuer certaines vérifications non vides nécessaires

Vérification non vide

Principalement pour détecter si l'e-mail est vide et si le mot de passe est vide, vérifiez si les mots de passe saisis deux fois sont cohérents.

//发起请求之前验证是否为空
if (hash['email'] === '') {
  $form.find('[name="email"]').siblings('.errors').text('请您输入邮箱')
  return false //精髓啊,不然没用了
}
if (hash['password'] === '') {
  $form.find('[name="password"]').siblings('.errors').text('请您输入密码')
  return false //精髓啊,不然没用了
}
if (hash['password_confirmation'] === '') {
    $form.find('[name="password_confirmation"]').siblings('.errors').text('请您再次输入确认密码')
    return false //精髓啊,不然没用了
}
if (hash['password'] !== hash['password_confirmation']) {
  $form.find('[name="password_confirmation"]').siblings('.errors').text('两次输入密码不匹配')
  return false //精髓啊,不然没用了
}
Copier après la connexion
  • Si vous oubliez d'écrire return, même s'il est vide, vous sauterez directement cette étape de détection et lancerez une requête ajax, alors n'oubliez pas d'écrire return false.

  • Il y aura un bug si vous l'écrivez comme ça. Lorsqu'un message d'erreur apparaît et que vous remplissez correctement les informations, le message d'erreur s'affiche toujours. Ceci est évidemment déraisonnable. Le message d'erreur devrait disparaître après avoir rempli les informations.

Apprenons Cookie ensemble

 $form.find('.errors').each((index, span) => {
     $(span).text('')
 })
Copier après la connexion

Utilisez le code jq ci-dessus pour résoudre ce bug.

Une fois la vérification non vide terminée, cela signifie que le navigateur a terminé le travail de collecte des données utilisateur et que le hachage peut être envoyé au serveur. L'étape suivante est la requête ajax.

Utilisez ajax pour soumettre des données

$.post('/sign_up', hash)
.then((response) => {
  //成功了就打印这个  
  console.log(response)
},
() => {
  //错误了打印这个
})
Copier après la connexion

Analyse formData côté serveur

Parce que formData est téléchargé morceau par morceau (la raison spécifique est légèrement compliquée, vous pouvez utiliser le limit, s'il y a beaucoup de formdata , il est impossible de tout télécharger en même temps), je ne peux pas l'écrire moi-même, donc je recherche des extraits de code pour analyser les formdata

google: node get post data

et encapsuler le code obtenu dans une fonction

function readBody(request) {
  return new Promise((resolve, reject) => {
      let body = []
      request.on('data', (chunk) => {
        body.push(chunk)
      }).on('end', () => {
        body = Buffer.concat(body).toString();
          resolve(body)
      })
    }
  )

}
Copier après la connexion

Comment utiliser l'extrait de code ci-dessus

...
if (path === '/sign_up' && method === 'POST') {
    readBody(request).then((body) => {
      let strings = body.split('&') //['email=1', 'password=2', 'password_confirmmation=3']
      let hash = {}
      strings.forEach(string => {
        //想得到类似这种的 string == 'email=1'
        let parts = string.split('=') //再用=分割,得到['email', '1']
        let key = parts[0]
        let value = parts[1]
        hash[key] = decodeURIComponent(value)//hash['email'] = '1'
      })
      let {email, password, password_confirmation} = hash //ES6的解构赋值
  }
  ...
Copier après la connexion

Lorsque le serveur reçoit toutes les données de formulaire, il est en fait une chaîne de chaînes en forme de email=1&password=2&password_confirmation=3

, nous envisageons donc d'utiliser des caractères & pour la diviser en tableaux.

  • Après avoir obtenu un tableau sous la forme de ['email=1', 'password=2', 'confirmation=3'], afin d'obtenir la forme de string = 'email=1', nous commençons à parcourir le tableau et divisons chaque élément du tableau selon =. Obtenez [email, 1]

  • en utilisant la méthode hash+[] fournie dans la deuxième section pour le traiter en hachage

Vérification simple sur côté serveur

Maintenant que le serveur a obtenu formdata, il doit effectuer une simple vérification, comme le format de l'email. S'il n'y a pas de problème, les données seront stockées dans la base de données. (Le niveau de vérification actuel est très basique et n'implique pas la fonction complète de vérification de l'enregistrement)

Travail de préparation avant vérification

Dans la section précédente, nous avons parfaitement encapsulé les données du formulaire dans le hachage Pour vérifier. , nous devons démonter le hachage et l'examiner un par un

C'est peut-être le moyen le plus direct

let email = hash['emai']
let password = hash['password']
let password_confirmation = hash['password_confirmation']
Copier après la connexion

Mais ES6 fournit une sorte de sucre syntaxique pour l'affectation de déstructuration, qui est très gentil. Intime...

let {email, password, password_confirmation} = hash
Copier après la connexion

Bug causé par @coding

D'accord, vérifions d'abord si le format de l'e-mail est correct.

我是菜鸟级校验邮箱,看到了邮箱的独特标志---@,最起码有这个标志才叫邮箱吧,也就是说没有这个标志,我就可以认为邮箱格式不对啊,翻译成代码就是

if (email.indexOf('@') === -1) {
  response.statusCode = 400
  response.write('email is bad') //单引号只是为了标记这是一个字符串
}
Copier après la connexion

很好,目前来说,事情的发展都很正常,直到一个bug的到来。

Apprenons Cookie ensemble

一个合法的邮箱,却进入了非法邮箱处理的代码片段里面……

Apprenons Cookie ensemble

毫无疑问,邮箱是合法的,代码也是合理的,那么出问题的必然是我,某个地方的理解有问题。

  • 找bug,把可能出错的代码片段分成几个区间,打log.

console.log(email.indexOf('@'))
console.log(email)
Copier après la connexion

Apprenons Cookie ensemble

没错,email这个字符串的@索引真的是-1,可是我的邮箱写的明明有@啊。

为啥呢,接着又打印出了email的内容,终于真相大白了,email字符串里面真的没有@

却发现了一串你没想到的%40,(⊙v⊙)嗯,没错了,这就是我认为的那个@的另一个形态。

  • 我在浏览器看到的只是浏览器想让我看到的东西而已,既然已经被浏览器处理了,那到了服务器端自然无法处理。

  • 那这个%40哪来的呢

Google走起,在w3schools的HTML URL Encoding Reference找到了解释(不是国内的w3school……)

URL encoding converts characters into a format that can be transmitted over the Internet.

URL编码把字符转化成了一种可以在互联网上传播的格式,也就是说,我在网页上看到的字符是被URL编码处理的结果。

  • 那接下来就去搞定什么是URL编码

搞定这个之前,文档先要让你明白啥是URL

Web browsers request pages from web servers by using a URL.

The URL is the address of a web page, like: https://www.w3schools.com.

Web浏览器通过使用URL从Web服务器请求页面。 该网址是网页的地址,例如:https://www.w3schools.com。


复习一下URL的组成6部分:

https://www.baidu.com/s?wd=he... 通过这个你就可以访问到一个 "唯一的" 网址

名字作用
https:协议
www.baidu.com域名
/s路径
wd=hello&rsv_spt=1查询参数
#5锚点
端口默认80

复习完了URL,继续搞URL编码

URLs can only be sent over the Internet using the ASCII character-set.

Since URLs often contain characters outside the ASCII set, the URL has to be converted into a valid ASCII format.

URL encoding replaces unsafe ASCII characters with a "%" followed by two hexadecimal digits.

URLs cannot contain spaces. URL encoding normally replaces a space with a plus (+) sign or with %20.

  • URL只能用ASCII编码在互联网之间发送。

  • 既然URL通常包括ASCII字符编码集之外的字符(很明显嘛,ASCII码表太少),所以URL必须转化成有效的ASCII格式。

  • 这是重点,URL编码使用%后面紧跟着两个16进制数字的编码格式来代替不安全的ASCII码表

  • URL不能包括空格。所以URL编码通常使用+号或者20%来代替空格。

继续往下翻,找到了%40

Apprenons Cookie ensemble

所以要把value的值解码回去

hash[key] = decodeURIComponent(value)
Copier après la connexion

decodeURIComponent() 方法用于解码由 encodeURIComponent 方法或者其它类似方法编码的部分统一资源标识符(URI)。毕竟URL属于URI

错误信息的提示方法

如果有了错,需要提示用户错了,后端写的代码,用户不一定看的懂,需要前端润色一下使用户看懂,或者前端和后端沟通一下,maybe后端脾气不好,前端也是暴脾气,所以应该选择一个前后端都要用的东西做桥梁,很明显JSON是完美的候选人。

if (email.indexOf('@') === -1) {
  response.statusCode = 400
  response.setHeader('Content-Type', 'application/json;charset=utf-8') //直接告诉浏览器我是json
  response.write(`
    {
      "errors": {
      "email": "invalid"
      }
    }
  `)
}
Copier après la connexion

这就合理多了,后台只管写个json给前台看,其他不管了,前台翻译一下给用户看喽~

那么前台如何获得这个json

$.post('/sign_up', hash)
.then((response) => {
  //成功了就打印这个  
  console.log(response)
},
(request, b, c) => {
   console.log(request)
   console.log(b)
   console.log(c)
})
Copier après la connexion

忘记了错误函数里面的参数是啥了,那就都打印出来看看。

Apprenons Cookie ensemble

可以看到,如果没用JSON的话,request对象里面有一个后端写的responseText属性可以利用。

Apprenons Cookie ensemble

设置了Content-Type:application/json;charset=utf-8之后,可以利用多出来的responseJSON属性,获得json的内容啊。

最终失败函数里面写

(request) => {
  let {errors} = request.responseJSON    
  if (errors.email && errors.email === 'invalid') {
    $form.find('[name="email"]').siblings('.errors').text('您输入的邮箱错啦')
  }
}
Copier après la connexion

校验邮箱是否已经存在了

var users = fs.readFileSync('./db/users', 'utf8')
try {
  users = JSON.parse(users) //[] JSON也支持数组
} catch (exception) {
  users = []
}
let inUse = false
for (let i = 0; i < users.length; i++) {
  let user = users[i]
  if (user.email === email) {
    inUse = true
    break
  }
}
if (inUse) {
  response.statusCode = 400
  response.setHeader('Content-Type', 'application/json;charset=utf-8')
  response.write(`
    {
      "errors": {
      "email": "inUse"
      }
    }
  `)
}
Copier après la connexion

本文并没有使用真正意义上的数据库,只是使用了简单的db文件做数据库,其实就是存的数组,也就是users其实就是数组[]

  • 之所以使用了try{}catch(){},是因为一旦除了错,可以将其初始化为空数组,后续代码可以继续执行,可能并不严谨,不过本文是侧重了解注册的思路的。

同样的,如果邮箱已经存在了,就提示用户

if (errors.email && errors.email === 'inUse') {
    $form.find('[name="email"]').siblings('.errors').text('这个邮箱已被注册啦')
}
Copier après la connexion

后端校验必须很严格,因为可以通过curl越过前端的校验。

Apprenons Cookie ensemble

Apprenons Cookie ensemble


把信息写入数据库

没有错误之后,就可以把信息写到数据库里面啦

 users.push({email: email, password: password})//是个对象啊
 var usersString = JSON.stringify(users)
 fs.writeFileSync('./db/users', usersString)
 response.statusCode = 200
Copier après la connexion

users实现是个对象,而对象是内存里面的东西,数据库里面应该存储的是字符串,所以用了JSON.stringify(users)

相关推荐:

JS前端缓存的实现方法及 Cookie的特点介绍

全面掌握Express cookie-parser中间件

JavaScript读取和写入cookie实例教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal