注册与登录(一)
- 注册(前端、服务器)
- 登录(前端、服务器)
只关注,注册登录的大体逻辑,没有实现邮箱密码校验。
博客代码,见:https://github.com/huahua029/jsdemo/tree/master/sign1.0
完整代码(包含简单的校验),见:https://github.com/huahua029/jsdemo/tree/master/sign2.0
注册
注册页面分为包含邮箱、密码、确认密码、提交的一个表单
一、发送GET请求,得到注册页面
当我们进入 /sign_up
页面,浏览器发送GET请求,服务器进行路由,将sign_up.html
作为response返回。
二、发送POST请求,将表单信息提交到服务器
当我们填写完信息后,点击注册进行提交,此时我们像服务器发送POST请求,我们的路径依然是sign_up
,只不过此时的method是POST
问题一:表单将信息提交后,服务器是如何接受的?(也就是如何处理这段信息)
不了解...google下:node http POST data
可以搜到这么一个方法(不使用框架):
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// at this point, `body` has the entire request body stored in it as a string
});
那我们就可以试一试,将其放入当前的路由中~
这个时候我们当前的服务器可以这样写:
...
else if (path === '/sign_up' && method === 'POST') {
let body = []
request.on('data', (chunk) => {
body.push(chunk)
}).on('end', () => {
body = Buffer.concat(body).toString()
console.log(body)
})
response.statusCode = 200
response.end()
}
...
经过测试,实际上没问题,会打印出email=1&password=2&password_confirmation=3
,这个时候,我们在服务器已经成功的接受表单传过来的数据。
鉴于我们后边会继续使用这种方法,拿到客户端传过来的数据,我们将其封装为一个函数。(肯定是异步拿,假设用户穿了好多的数据,不可能一次拿完...),我们使用Promise
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) //成功了就整出去
})
})
}
此时,我们将路由也做出修改:
readBody(request).then(
(body) => {
console.log(body)
response.statusCode = 200
response.end()
})
测试结果,没有任何问题。
问题二:如何处理数据(服务器解析数据)
传过来的数据比如是email=1&password=2&password_confirmation=3
,当然是当做字符串处理,就是使用split花式分割,再存进去就可以啦~
var string = 'email=1&password=2&password_confirmation=3'
var s = string.split('&')
var hash = {}
s.forEach((item)=>{
var part = item.split('=')
var key = part[0]
var value = part[1]
hash[key] = value
})
console.log(hash) // {email: "1", password: "2", password_confirmation: "3"}
好了,既然可以读取客户端表单传过来的数据,我们就该进行下一步~
问题三: 读取到的数据,如何存储~(当然是选择数据库,不过我不会...用文件存了...)
当然
一、用readFileSync打开文件
var users = fs.readFileSync('./db/users', 'utf8')
二、给users中设置我们获取到的信息
users.push({ email: email, password: password })
三、用writeFileSync写入。
fs.writeFileSync('./db/users', users)
这三步下来看似挺完美,实际上会出问题:
第二步的bug,显示users没有push方法,可能我们的users存在问题。我们可以使用try-catch
来重新设置users
第三步的写入,实际上我们需要使用JSON.stringify
将字符串转化为JSON数据再写入
还有一个问题,就是写入的@符号,显示为%40,我们需要使用decodeURIComponent,将已编码 URI 中所有能识别的转义序列转换成原字符。
所以完整的代码为:
var users = fs.readFileSync('./db/users', 'utf8')
try {
users = JSON.parse(users)
} catch (ex) {
users = []
}
users.push({ email: email, password: password })
var usersString = JSON.stringify(users)
fs.writeFileSync('./db/users', usersString)
response.statusCode = 200
response.end()
截止到这里,我们已经解决了注册的问题。
登录
登录页面有邮箱和密码,进入sign_in
,GET得到登录页面,填写完信息后,点击登录提交表单信息到服务器,服务器将收集到的信息与数据库中的数据进行对比,若邮箱密码正确,返回200,若错误返回401。
与登录页面类似,问题也是一样的就不累述。代码:
readBody(request).then((body) => {
var strings = body.split('&')
var hash = {}
strings.forEach((item) => {
var part = item.split('=')
var key = part[0]
var value = part[1]
hash[key] = decodeURIComponent(value)
})
let { email, password } = hash
var users = fs.readFileSync('./db/users', 'utf8')
try {
users = JSON.parse(users)
} catch (ex) {
users = []
}
let found
for (let i = 0; i < users.length; i++) {
if (users[i].email === email && users[i].password === password) {
found = true
break
}
}
if (found) {
response.statusCode = 200
} else {
response.statusCode = 401
}
response.end()
})
cookie
来自MDN的解释
HTTP Cookie(也叫Web Cookie或浏览器Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。
在本例中试试
我们通过set-cookie设置响应头
response.setHeader('Set-Cookie', `sign_in_email=${email}`)
接下来,我们在客户端设置,验证成功,返回200后,我们跳转到首页
$.post('/sign_in', hash)
.then((response) => {
window.location.href = '/'
}, (request) => {
alert('邮箱与密码不匹配')
})
接下来得到首页的这次请求,我们就可以发现,请求中有:
Cookie: sign_in_email=huazhen007@outlook.com
这样服务器就知道用户的登录信息了。
cookie特点
1.服务器通过set-cookie响应头设置cookie
2.浏览器得到cookie之后,每次请求都要带上cookie
3.服务器读取cookie就知道登录用户的信息(email)
问题:
1.在chrome登录,在ie中肯定不能用
2.cookie存在哪,win中存在c盘一个文件中
3.cookie可以作假!
4.cookie有效期。默认的有效期是20分钟左右。后端可以强制设置有效期。
cookie设置
HttpOnly,js不能修改cookie
其他
form表单提交的默认操作,e.preventDefault()
jquery的属性选择器
find()方法,用于遍历后代
split用于分割
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。如果要检索的字符串值没有出现,则该方法返回 -1。
decodeURIComponent
window.location.href
replace
each()