cookie 假如非要用汉语邃晓的话应当是 一段小型文本文件,由网景的创始人之一的
卢 蒙特利在93年发现。上篇是熟习一下注册的大抵流程,下篇熟习登录流程以及真正的Cookie
完成基础的注册功用
我们翻开网站,阅读网站,最常见的两个操纵就是注册以及登录,所以有必要探究一下这两个功用怎样完成的。
当地模仿,当输入localhost:8080/sign_up
的时刻,阅读器提议get
要求,服务器给你相应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()
}
CSS规划的几个小坑
在写sign_up.html
的时刻,注重几点css学问:
- 假如想让你的登录页面的body占满全部屏幕,跟着窗口的大小变化而变化的话,能够写
body, html{height: 100%}
//也许
body{min-height: 100%}
html{height: 100%}
//不能这么写
body, html{min-height: 100%}
固然了,实际上这么写就能够了
body{min-height: 100vh}
-
label
标签是display: inline
,不能设置宽度,行内元素则会依据行内内容自适应宽度,所以行内元素设置width是没有用果的。改成inline-block就能够了
取得用户的数据
既然是注册的需求,那末我们主要关注的点就是–用户的注册信息我们怎样取得呢
挑选合理的数据结构存储数据是很主要的。
- 每一个
input
的name
能够运用数组存储 -
input
的value
应当运用hash
,也就是对象来存储。 - 上述的套路会一向用下去,
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
})
终究hash
内里存储的就是
{
'email': '...',
'password': '...',
'password_confirmation': '...'
}
到现在为止我们把用户的数据封装到了一个对象内里了。
不过在把hash用ajax发出去之前要先举行一些必要的非空考证
非空考证
主如果检测邮箱是不是为空、暗码是不是为空、两次输入的暗码是不是一致。
//提议要求之前考证是不是为空
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 //精华啊,不然没用了
}
- 假如遗忘写return的话,纵然你为空了照样会直接超出这一步检测,去提议ajax要求的,所以肯定不要忘了写上return false.
- 假如仅仅这么写的话会有一个bug。当涌现毛病提醒后,你把信息填对了,毛病信息依旧显现,这显然是不合理的。应当填入信息后,毛病信息就消逝的。
$form.find('.errors').each((index, span) => {
$(span).text('')
})
运用上述的jq代码来处置惩罚这个bug即可。
非空考证完了以后,意味着阅读器网络用户数据的事变完成了,能够把hash发到服务器端了,接下来就是ajax要求了。
运用ajax提交数据
$.post('/sign_up', hash)
.then((response) => {
//胜利了就打印这个
console.log(response)
},
() => {
//毛病了打印这个
})
服务器端剖析formData
由于formData是一段一段上传的(详细缘由略庞杂,能够取极限法,假如formdata许多,不能够一会儿上传过来),本身不会写,就去搜刮代码片断剖析formdata
google: node get post data
把取得的代码封装成了一个函数
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)
})
}
)
}
怎样运用上述代码片断呢
...
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的解构赋值
}
...
当服务器端吸收到了一切的formdata数据后,实际上是一串形如email=1&password=2&password_confirmation=3
的字符串,所以我们斟酌运用&
字符支解成数组。
- 获得一个形如
['email=1', 'password=2', 'confirmation=3']
的数组以后,我们为了获得string = 'email=1'
这类情势的,最先遍历数组,把数组的每一个元素根据=
支解,获得[email, 1]
- 用第二小节供应的
hash+[]
要领,处置惩罚成hash
服务器端简朴的校验
既然服务器端已取得了formdata
了,那末应当举行一下简朴的校验,比方邮箱的花样,没有题目了就把数据存到数据库内里。(现在校验程度很入门,没有涉及到完整的注册校验功用)
校验前的准备事变
上一节我们把formdata圆满的封装到了hash内里,为了校验我们要把hash再拆开一个一个的看
也许这么做是最直接的
let email = hash['emai']
let password = hash['password']
let password_confirmation = hash['password_confirmation']
不过ES6供应了一种解构赋值的语法糖,很甜很知心……
let {email, password, password_confirmation} = hash
由@编码激发的bug
好了,我们这一步就先看看邮箱花样是不是准确。
我是菜鸟级校验邮箱,看到了邮箱的奇特标志—@
,最起码有这个标志才叫邮箱吧,也就是说没有这个标志,我就能够以为邮箱花样不对啊,翻译成代码就是
if (email.indexOf('@') === -1) {
response.statusCode = 400
response.write('email is bad') //单引号只是为了标记这是一个字符串
}
很好,现在来讲,事变的生长都很一般,直到一个bug的到来。
一个正当的邮箱,却进入了不法邮箱处置惩罚的代码片断内里……
毫无疑问,邮箱是正当的,代码也是合理的,那末出题目的必定是我,某个处所的邃晓有题目。
- 找bug,把能够失足的代码片断分红几个区间,打log.
console.log(email.indexOf('@'))
console.log(email)
没错,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
。
所以要把value
的值解码归去
hash[key] = decodeURIComponent(value)
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"
}
}
`)
}
这就合理多了,背景尽管写个json给前台看,其他不管了,前台翻译一下给用户看喽~
那末前台怎样取得这个json
呢
$.post('/sign_up', hash)
.then((response) => {
//胜利了就打印这个
console.log(response)
},
(request, b, c) => {
console.log(request)
console.log(b)
console.log(c)
})
遗忘了毛病函数内里的参数是啥了,那就都打印出来看看。
能够看到,假如没用JSON的话,request对象内里有一个后端写的responseText属性能够应用。
设置了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('您输入的邮箱错啦')
}
}
校验邮箱是不是已存在了
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"
}
}
`)
}
本文并没有运用真正意义上的数据库,只是运用了简朴的db文件做数据库,实在就是存的数组,也就是users实在就是数组[]
。
- 之所以运用了
try{}catch(){}
,是由于一旦除了错,能够将其初始化为空数组,后续代码能够继承实行,能够并不严谨,不过本文是着重相识注册的思绪的。
一样的,假如邮箱已存在了,就提醒用户
if (errors.email && errors.email === 'inUse') {
$form.find('[name="email"]').siblings('.errors').text('这个邮箱已被注册啦')
}
后端校验必需很严厉,由于能够经由过程curl
超出前端的校验。
把信息写入数据库
没有毛病以后,就能够把信息写到数据库内里啦
users.push({email: email, password: password})//是个对象啊
var usersString = JSON.stringify(users)
fs.writeFileSync('./db/users', usersString)
response.statusCode = 200
users完成是个对象,而对象是内存内里的东西,数据库内里应当存储的是字符串,所以用了JSON.stringify(users)
好啦,上篇注册篇完毕啦,下篇讲一讲怎样登录以及Cookie
上台
相干代码见sign_up.html