首先说一下,我上面说的放到session里不好,指的是放到服务器内存。而且我down下来了老师的代码,没发现将状态保存到session的,所以晚上用了点时间,自认为算是完美解决吧:
$ npm install uuid
$ npm install redis
一、登录、登出功能
//Redis
let redis = require('redis')
let client = redis.createClient()
//uuid
const uuidv4 = require('uuid/v4') //v4是随机数
//登录
router.post('/login', function (req, res, next) {
let param = {
userName: req.body.userName,
userPwd: req.body.userPwd
}
User.findOne(param, (err, doc) => {
if (err) {
res.json({
status: "1",
msg: err.message
})
} else {
let uuid = uuidv4()
//存至cookie
res.cookie("token", uuid, {
path: "/",
maxAge: 1000 * 60 * 60 //存储1小时
})
//存至redis, 1小时失效
client.set(`token-${uuid}`, JSON.stringify(doc))
client.expire(`token-${uuid}`, 60 * 60);
res.json({
status: "0",
msg: "",
result: doc.userName
})
}
})
});
//登出
router.post('/logout', function (req, res, next) {
let cookie = req.cookies.token
if (cookie) {
//清除redis
client.del(`token-${cookie}`)
//清除cookie
res.cookie("token", "", {
path: "/",
maxAge: 0
})
}
res.json({
status: "0",
msg: "",
result: ""
})
});
二、登录拦截功能
//Redis
let redis = require('redis')
let client = redis.createClient()
client.on('ready', function (err) {
console.log('Redis ready');
});
//拦截放在路由之前,只要有请求进来就先判断的
app.use(function (req, res, next) {
//接口白名单
if (
req.originalUrl == '/users/login' ||
req.originalUrl == '/users/logout' ||
req.path == "/goods/list" //因为后面有参数,只取接口的pathName. 或者 req.originalUrl.indexOf('/goods/list') > -1
){
next()
return
}
//验证登录状态
let cookie = req.cookies.token
//查询cookie
if (!cookie) {
res.statusCode = 401
res.json({
status: '401',
msg: '当前未登录',
result: ''
});
}
//查询redis
client.get(`token-${cookie}`, (err, reply) => {
if (!reply) {
res.statusCode = 401
res.json({
status: '401',
msg: '当前未登录',
result: ''
});
}else next()
})
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/goods', goodsRouter);
这样的话,如果没有登录,响应码设置为401,前端就可以通过axios拦截器拦截到401,跳转到登录页或者提醒登录。