Home > Web Front-end > JS Tutorial > Let's learn Cookie together

Let's learn Cookie together

小云云
Release: 2018-02-09 14:35:46
Original
1835 people have browsed it

This article mainly talks about cookies together with everyone. If you have to understand cookies in Chinese, it should be a small text file, invented by Lou Monterey, one of the founders of Netscape, in 1993. Hope this article can help everyone.

Implementing basic registration functions

We open the website and browse the website. The two most common operations are registration and login, so it is necessary to explore how these two functions are implemented.

Local simulation, when you enter localhost:8080/sign_up, the browser initiates a get request, and the server responds to you sign_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()
 }
Copy after login

Several pitfalls in CSS layout

When writing sign_up.html, pay attention to some css knowledge:

  1. If you want the body of your login page to occupy the entire screen and change as the size of the window changes, you can write

body, html{height: 100%}
//或者
body{min-height: 100%}
html{height: 100%}
//不能这么写
body, html{min-height: 100%}
Copy after login

Of course, this is how you actually write it. The

body{min-height: 100vh}
Copy after login
  1. label label is display: inline, the width cannot be set, inline elements will adapt their width according to the inline content , so setting width on inline elements has no effect. Just change it to inline-block

Let's learn Cookie together

##Get user data

Since it is a registration requirement, our first focus is-how do we obtain the user's registration information?

It is very important to choose a reasonable data structure to store data.

  1. The

    name of each input can be stored using an array

  2. input's value should be stored using hash, which is an object.

  3. The above routine will continue to be used, the combination of

    hash+[].

  4. //使用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
    })
    Copy after login
Finally

hash is stored in

{
  'email': '...',
  'password': '...',
  'password_confirmation': '...'
}
Copy after login

So far we have encapsulated the user's data into an object.

However, before sending the hash using ajax, some necessary non-empty verification must be performed first

Non-empty verification

The main purpose is to detect whether the email address is empty and whether the password is If empty, check whether the passwords entered twice are consistent.

//发起请求之前验证是否为空
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 //精髓啊,不然没用了
}
Copy after login

  • If you forget to write return, even if it is empty, you will directly skip this step of detection and initiate an ajax request, so don’t forget to write return false.

  • There will be a bug if you just write it like this. When an error message appears and you fill in the information correctly, the error message is still displayed. This is obviously unreasonable. The error message should disappear after filling in the information.

Let's learn Cookie together

 $form.find('.errors').each((index, span) => {
     $(span).text('')
 })
Copy after login

Use the above jq code to solve this bug.

After the non-empty verification is completed, it means that the browser has completed the work of collecting user data, and the hash can be sent to the server. The next step is the ajax request.

Use ajax to submit data

$.post('/sign_up', hash)
.then((response) => {
  //成功了就打印这个  
  console.log(response)
},
() => {
  //错误了打印这个
})
Copy after login

Server-side parsing formData

Because formData is uploaded piece by piece (the specific reason is slightly complicated, you can use the extreme method. If there is a lot of formdata, no Maybe upload it all at once), I don’t know how to write it, so I search for code snippets to parse formdata

google: node get post data

and encapsulate the obtained code into A function

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)
      })
    }
  )

}
Copy after login

How to use the above code snippet

...
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的解构赋值
  }
  ...
Copy after login

When the server receives all the formdata data, it is actually a string of the form

email=1&password=2&password_confirmation=3

string, so we consider using

& characters to split it into an array.

  • After getting an array in the shape of

    ['email=1', 'password=2', 'confirmation=3'], we want to get string = 'email=1'In this form, start traversing the array, split each element of the array according to =, and get [email, 1]

  • Use the

    hash+[] method provided in the second section to process it into hash

Simple verification on the server side

Now that the server has obtained

formdata, it should perform a simple verification, such as the format of the email. If there is no problem, the data will be stored in the database. (The current verification level is very basic and does not involve the complete registration verification function)

Preparation work before verification

In the previous section, we perfectly encapsulated the formdata into the hash. To verify, we need to disassemble the hash one by one and look at it one by one.

Perhaps this is the most direct way

let email = hash['emai']
let password = hash['password']
let password_confirmation = hash['password_confirmation']
Copy after login

But ES6 provides a kind of syntax sugar for destructuring assignment, which is very sweet and considerate... …

let {email, password, password_confirmation} = hash
Copy after login

Bug caused by @coding

Okay, let’s first check whether the email format is correct.

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

if (email.indexOf('@') === -1) {
  response.statusCode = 400
  response.write('email is bad') //单引号只是为了标记这是一个字符串
}
Copy after login

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

Let's learn Cookie together

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

Let's learn Cookie together

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

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

console.log(email.indexOf('@'))
console.log(email)
Copy after login

Let's learn Cookie together

没错,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

Let's learn Cookie together

所以要把value的值解码回去

hash[key] = decodeURIComponent(value)
Copy after login

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"
      }
    }
  `)
}
Copy after login

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

那么前台如何获得这个json

$.post('/sign_up', hash)
.then((response) => {
  //成功了就打印这个  
  console.log(response)
},
(request, b, c) => {
   console.log(request)
   console.log(b)
   console.log(c)
})
Copy after login

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

Let's learn Cookie together

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

Let's learn Cookie together

设置了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('您输入的邮箱错啦')
  }
}
Copy after login

校验邮箱是否已经存在了

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(&#39;Content-Type&#39;, &#39;application/json;charset=utf-8&#39;)
  response.write(`
    {
      "errors": {
      "email": "inUse"
      }
    }
  `)
}
Copy after login

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

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

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

if (errors.email && errors.email === &#39;inUse&#39;) {
    $form.find(&#39;[name="email"]&#39;).siblings(&#39;.errors&#39;).text(&#39;这个邮箱已被注册啦&#39;)
}
Copy after login

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

Let's learn Cookie together

Let's learn Cookie together


把信息写入数据库

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

 users.push({email: email, password: password})//是个对象啊
 var usersString = JSON.stringify(users)
 fs.writeFileSync(&#39;./db/users&#39;, usersString)
 response.statusCode = 200
Copy after login

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

相关推荐:

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

全面掌握Express cookie-parser中间件

JavaScript读取和写入cookie实例教程

The above is the detailed content of Let's learn Cookie together. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template