前两天使用cookie和session实现了这个流程,后来又添加了redis缓存,能在重起服务的时候保持session信息不丢失,实现持久化,但是每次都需要客户端和服务端的信息各自存储来尽进行比较,http请求是无状态的,所有我们可以模仿jwt || json web token 来实现整个流程我们。
我们不再需要cookie和session这两个中间件来加持,所有我们规定:
1.在验证码的时候发送前端一个token,用来标识验证码
2.在前端用户登录的时候需要带上前一个token,然后对比验证码,账号和密码的正确操作需求,紧接着来一个正式的token,这个token才是我们真正的token。这两个接口(验证码接口、登录接口都是以参数的形式给前端发送token,但是前端来访问我的接口需要在headers上加上我的token。)
话不多说了,说多了都是寂寞…长路漫漫,无心睡眠…
这是我引入的所有模块包括自己封装的还有引入第三方的
var express = require('express');
//uuid模块 生成唯一的uuid 用来标识用户的唯一性
const {
v4: uuidv4 } = require('uuid');
//m密码使用md5模块进行的加密
const md5 = require('md5');
//引入router模块 创建后端路由
var router = express.Router();
//自己封装的链接数据的模块
var Db = require('../public/javascripts/Db')
//自己封装的 给前端返回前加一层对象,使格式统一
var endMassage = require('../public/javascripts/endMassage')
//引入验证码第三方模块
let captcha = require('svg-captcha')
//自己定义路由中间件模块 为了接口调用打印的时候多几行空行 没啥用
router.use((req, res, next) => {
console.log("");
console.log("");
console.log("");
console.log("");
console.log("");
next()
})
验证码接口:
// 验证码配置信息
const options = {
size: 4, // 验证码长度(显示几个字符)
ignoreChars: '0o1i', // 验证码字符中排除 0o1i
fontSize: 34, // 验证码的字体大小
width: 90, // 验证码的宽度
height: 40, // 验证码的高度
background: '#cc9966', // 验证码的背景颜色
color: 'red'
};
//验证码接口
var codeStr = ''
router.get('/getCaptchaCode', (req, res) => {
let code = captcha.create(options)
codeStr = code.text
console.log("获取验证码接口", codeStr);
res.send(endMassage({
data: "验证码获取成功", code: code.data, token: md5(codeStr.toUpperCase()) }))
})
登录接口:
//登录注册接口 有账号 直接登录 没账号 注册
router.get('/login', function (req, res, next) {
console.log("登录接口");
let token = req.headers.token
if (!token) res.send(endMassage({
data: "没用权限", code: 0 }))
let {
username, password, code } = req.query
console.log(username, 'username===');
console.log(code, md5(code.toUpperCase()), token, "服务端的验证码和前端传送过来的验证码");
if (token != md5(code.toUpperCase())) {
res.send(endMassage({
data: "请输入正确验证码", code: 0 }))
return
}
console.log("===========验证码匹配正确============");
// console.log(username, password, 'username, password,randomStr');
if (!username || !password) {
res.send(endMassage({
data: "请输入账号或密码", code: 0 }))
return
}
//查询账号是否存在
Db.DBFun(`select username,password,uuid from user where username='${
username}'`, (data) => {
if (data.length) {
//存在验证密码是否正确
// token: String(username).split('').reverse().join('') + 'zjjq' + new Date().getTime()
if (data[0].password == md5(password)) {
console.log("密码正确");
console.log(String(username).split('').reverse().join(''), 'String(username).split()');
res.send(endMassage({
data: "登录成功", code: 1, uuidStr: data[0].uuid, token: String(username).split('').reverse().join('') + 'zjjq' + new Date().getTime() }))
}
else res.send(endMassage({
data: "密码错误", code: 0 }))
} else {
//账号不存在注册
let uuidStr = uuidv4()
let passwordStr = md5(password)
Db.DBFun(`insert into user(password,username,uuid) values ('${
passwordStr}','${
username}','${
uuidStr}') `, (insertInfo) => {
res.send(endMassage({
data: "注册成功", uuidStr, token: String(username).split('').reverse().join('') + 'zjjq' + new Date().getTime() }))
})
}
})
});
上面这两个接口都是在判断有没有正式token的自定义中间件之前,验证码接口主要是生成验证码,生成一个token给前端,在登录接口,我首先你判断了有没有token,然后判断验证码是否输入正确,紧接着判断了账号是否存在,没存在返回密码错误,存在密码正确,登录成功,不存在注册成功,然后返回一个正式的token,这个token我也是要求前端在请求头上给我带来,下面是我的自定义中间件,其实也就是个函数:
//token中间件
router.use((req, res, next) => {
let token = req.headers.token
if (!token) {
console.log("===没有权限===");
res.send(endMassage({
data: "没有权限", code: 0 }))
}
let massage;
let startTime;
let endTime = new Date().getTime()
try {
token ? massage = token.split('zjjq')[0].split('').reverse().join('') : massage = '未登录'; //取用户名
} catch{
res.send(endMassage({
data: "没有权限", code: 0 }))
}
console.log(`**********${
new Date().toLocaleString()}有人访问接口${
req.url} ===用户名是:${
massage}===***********`);
token ? startTime = token.split('zjjq')[1] : 123
endTime - startTime > 60 * 1000 * 60 ? res.send(endMassage({
data: "身份验证过期,请从新登录", code: 0 })) : '' //一小时过期
console.log("===开始判断是否有权限===");
if (massage == '未登录') {
console.log("===没有权限===");
res.send(endMassage({
data: "没有权限", code: 0 }))
}
else {
Db.DBFun(`select username,password,uuid from user where username='${
massage}'`, (data) => {
if (data.length) {
console.log("===ss有权限===");
next()
} else {
console.log("===没用有权限,用户名没有查到===");
res.send(endMassage({
data: "没有权限", code: 0 }))
}
})
}
})
主要是根据传来的token判断有没有权限访问呢除了验证码接口和登录接口。
最后将代码暴漏出去
//这是中间件后面的接口,访问前会自动先走token中间件进行判断有没有权限
router.use('/user', require('./indexR/changeUser'))
router.use('/pcacode', require('./indexR/PCAcode'))
module.exports = router;
上面流程图来自网络,如侵权请联系删除。