这段时间正好做有关的网页注册登录功能,想了想还是写一篇博客记录一下功能实现的流程,方便以后查阅。
我先把注册和登录的各种操作与判断流程分别说一下,方便理解。
注册
- 注册页面最重要的四部分是注册邮箱、密码、确认密码与注册按钮 。用户分别输入邮箱、密码与确认密码后点击注册按钮完成注册。
- 前端部分要做的事主要是判断用户是否在以上三个部分输入了信息,接着判断邮箱的格式是否正确(前端也可不进行判断邮箱的格式,因为后端服务器也会判断一次)、密码与确认密码两个部分的内容是否相同。
- 当用户内容输入正确后,客户端会将用户所输入的内容传给服务器。服务器得到信息后会再一次判断信息的格式等是否符合要求,无误后将得到的信息与数据库中的信息作比较,如有重复则提示前端邮箱已被注册,无重复则将信息存入数据库并提示前端注册成功。
注册部分前端代码
前端html部分主要是在form
表单加input
标签,利用form
标签来提交HTTP请求。
<form id="formSignUp">
<div>
<label for="email">邮箱</label>
<input type="text" name="email" id="email">
<span class="error"></span>
</div>
<input type="submit" value="注册">
</form>
前端JS部分代码主要是判断用户是否有输入内容、输入内容格式是否正确。
// 以下JS代码引用JQuery库,使用JQuery语法
let $form = $('#formSignUp')
let hash = {} // 声明一个空对象
$form.on('submit', (e)=>{ // 监听submit事件
e.preventDefault() // 取消默认事件
$form.find('.error').each((index, error)=>{ // 清空所有具有error属性的span标签的文本内容
$(error).text('')
})
let list = ['email']
list.forEach((name)=>{ // 遍历list数组
let value = $form.find(`[name="${name}"]`).val() // 取得用户所输入的内容
hash[name] = value // 将用户输入的内容存入空对象中,如: {email: '374xxxxxx@qq.com'}
})
if(hash.email === ''){ // 判断用户是否有输入
$form.find('#email').siblings('.error').text('请输入邮箱') // 如果用户每天输入信息,则在span标签中写入'请输入邮箱'
return
}
// 使用JQuery中AJAX的API,以下是Ajax函数的简写形式
$.post('/sign_up', hash) //使用HTTP POST请求,请求路径'/sign_up',并发送给服务器一个对象
then((response)=>{ // 请求成功
alert('注册成功')
window.location.href = '/sign_in' // 跳转到新的路径
},(request)=>{ // 请求失败
let {errors} = request.responseJSON // 使用ES6语法解析赋值,取得服务器返回的内容
if(errors.email && errors.email === 'invalid'){ // 判断服务器返回的内容
$form.find('#email').siblings('.error').text('邮箱格式错误')
}else if(errors.email && errors.email === 'used'){
$form.find('#email').siblings('.error').text('该邮箱已被使用')
}
})
})
注册部分后端代码
后端简易服务器使用nodejs搭建,如何搭建不是这篇博客主要讨论的,这里只介绍提取用户信息、判断用户信息与简单的存储数据的代码。(主要我也不太懂 - -)
下面这段代码是用来让服务器提取客户端POST请求的第四部分内容(请求体),这是我在Stack Overflow
上面找到的。这么写的主要原因是请求的第四部分不是一次性上传完毕的,它是服务器一段一段的获取到的。在服务器将所有请求体都获取到并放入body数组中之后,body = Buffer.concat(body).toString()
这段代码就可以用字符串形式展示所有的请求体。
let body = []
request.on('data', (chunk) => {
body.push(chunk)
}).on('end', () => {
body = Buffer.concat(body).toString()
console.log(body)
})
下面这段代码就是分解请求体,从请求体中获取数据。比如请求体为'email=1&password=1&password_confirmation=1'
let hash = {} // 声明一个对象
body.split('&').forEach((part) => {
// 将字符串形式的请求体以'&'为界分割,转成一个数组并遍历这个数组。
//例如:['email=1','password=1','password_confirmation=1']
let parts = part.split('=') // 操作同上,例如:['email', '1']
let key = parts[0]
let value = parts[1]
hash[key] = decodeURIComponent(value)
// 例如{email: '1'}, decodeURIComponent() 这个api是对编码后的URI字符进行解码
})
let { email, password, password_confirmation } = hash
以下代码是用以判断服务端接受的数据email格式正确与否。
if (email.indexOf('@') === -1) { // 判断email是否含有@这个字符
response.statusCode = 400 // email中没有@字符,返回状态码400
response.setHeader("Content-Type", "application/json; charset=utf8") // 设置响应头
response.write(`{ // 服务端返回JSON格式字符串
"errors": {
"email": "invalid"
}
}`)
}
在服务器判断请求体的数据(如email
)没有格式错误的问题后就需要判断此email
是否有被注册过。主要方式就是读取数据库文件,查看里面是否有相同的email
数据。
let users = fs.readFileSync('./db/users.json', 'utf8') // 读取数据库文件,这里数据库格式我是以JSON格式储存
// 这里try、catch的用法主要是防止数据库中的格式出错导致程序无法运行。
//如果try中的语法出错(即数据库格式错误),就执行catch中的语句,清空数据库。
try {
users = JSON.parse(users) // 将JSON字符串转换为对象
} catch (error) {
users = []
}
let inUsers = false
for (let i = 0; i < users.length; i++) { // 遍历整个数据库对象
if (users[i].email === email) { // 判断数据库中是否存在请求体的数据
inUsers = true
break
// 如果存在将变量inUsers的值改为true并跳出循环
}
最后这一部分就是将正确的数据写入数据库内,现在注册部分的前端与后端代码都结束了,接下来我要说登录部分了。
if (inUsers) {
response.statusCode = 400
response.setHeader("Content-Type", "application/json; charset=utf8")
response.write(`{
"errors": {
"email": "used"
}
}`)
} else { //email没有被注册过
users.push({ email: email, password: password }) // 将数据写入数组中
let usersString = JSON.stringify(users) // 将其转为JSON格式
fs.writeFileSync('./db/users.json', usersString) // 将数据写入数据库内
response.statusCode = 200 // 返回状态码200
}
登录
- 登录页面最重要的三部分是登录邮箱、密码与登入按钮 。用户分别输入邮箱、密码后点击登录按钮进行登录操作。
- 前端部分要做的事主要是判断用户是否在以上两个部分输入了信息,接着判断邮箱的格式是否正确(前端也可不进行判断邮箱的格式,因为后端服务器也会判断一次)。
- 当用户内容输入正确后,客户端会将用户所输入的内容传给服务器。服务器得到信息后会再一次判断信息的格式等是否符合要求,无误后将得到的信息与数据库中的信息作比较。
- 如果在数据库中能找到邮箱和密码与传入信息相同,则服务器设置cookie并返回HTTP状态码200给客户端,前端得到登录成功的信息就跳转到登录成功的页面;如果不同则返回HTTP状态码401给客户端,让客户端提示用户邮箱与密码不匹配、登录失败。
登录部分前端代码
登录的前端部分代码与注册的大体相同,逻辑也差不多,这里我就不写出来了。
登录部分后端代码
登录部分有些代码与注册部分一样,像取得请求体中的信息那部分我就没有写出。
let users = fs.readFileSync('./db/users.json', 'utf8') // 读取数据库信息
let usersList = JSON.parse(users) // 将JSON格式的数据库信息转为对象
let found
for (let i = 0; i < usersList.length; i++) {
let user = usersList[i]
if (user.email === email && user.password === password) { // 判断用户输入信息是否与数据库中的信息匹配
found = true
break
}
}
if (found) {
response.setHeader('set-Cookie', `sign_in_email=${email}`) // 匹配成功,设置cookie返回给客户端
response.statusCode = 200 // 返回HTTP状态码200
} else {
response.statusCode = 401 // 匹配失败,返回状态码401,提示用户登录失败
}
Cookie
前面我有提到cookie这个东西,Cookie主要是指某些网站为了辨别用户的身份而存储在用户本地终端上的数据。那接下来我就简单介绍一下cookie是什么、有什么特点。
1.Cookie是什么?
- cookie是客户端访问服务器后,服务器传给客户端的一段数据。
- 客户端需要保存这段数据,不得轻易删除。
- 以后每次客户端访问该服务器都必须带上这段数据。
1.Cookie有什么特点?
- 服务端通过
Set-Cookie
响应头设置Cookie。 - 客户端得到Cookie之后,每次访问相同域名的网页时都要带上这个Cookie。
- 服务器读取Cookie就知道了用户的登录信息。
- 客户端要在一段时间内保存这个Cookie,
- Cookie默认在用户关闭页面后失效,但是后端代码可以任意设置过期时间。
- Cookie的存储大小为4K。
以上我简单介绍了一下Cookie,想要了解更多的Cookie知识可以去MDN查询了解。Cookie有一个很大的缺点那就是稍微有点前端知识就可以随意串改Cookie,这样会导致有人恶意入侵获取所有用户隐私信息,为了防止这种情况出现配合session来加强Cookie的安全性,具体如何实现各位可以百度一下(or google)。
至此网页注册与登录两个部分的过程代码解析就结束了,看到这里你对网页注册和登录功能是如何实现的会有一个大概的了解,但是这么多代码可能看起来就会害怕(哈哈哈,我也是),如果愿意你可以有空自己写一个demo实现一下,这样会加深理解!
PS:我现在还是一个前端初学者,如果文中有什么地方写的不准确麻烦提出,我会尽快修改的!
PSS:如果你想看全部代码请点击它--->注册和登录代码
PSSS:之前说的要写JSONP与AJAX的博客要延后了,最近写了个小玩意就是眼球会跟着鼠标转动,过两天写篇博客演示一下如何用JS实现这个功能~(不知道要拖到啥时候写)