基于cookie-session方式
- 客户端使用账号密码登录
- 服务端对账号密码进行验证并生成session对象
- 之后服务端将sessionid返回
- 客户端在浏览器端保存sessionid在之后客户端发送请求时会带上sessionid到服务器
- 最后服务端接收到sessionid后会与之前保存的进行对比以确认用户身份
基于jwt方式(json-web-token)
1、客户端用户使用账号密码登录
2、服务端进行验证并生成jwt(需要自己设置密钥,服务端根据密钥生成的jwt)
3、服务端将jwt返回
4、客户端在浏览器中保存jwt(也就是保存服务端传过来的token)
5、客户端发送请求时会附带上jwt到服务器
6、服务端收到jwt后需验证jwt是否有效,有效则放行
(jwt的有效期是一天,可以手动修改失效时间)
在第二段中,一般存储的就是用户id之类的信息,不建议携带用户密码这类重要信息,因为jwt容易被解析,导致用户信息泄露
//生成token
generateToken(data) {
return jwt.sign(data, constant.secret, {
拦截器
expiresIn: '60000' //ms 1d---1天
})
},
// 用户登录接口
login: function(req, res) {
let {
account,
password
} = req.body;
userService.findUser(account, password)
.then(data => {
if (data) {
let result = {
data: data,
msg: "用户登录成功"
}
let jwt = operations.generateToken(result);
result.token = jwt;
res.status(200).json(result)
logger.info("用户登录成功")
} else {
res.status(400).json({
"msg": "用户登录失败"
})
logger.info("用户登录失败")
}
})
},
拦截器(根据jwt失效时间判断是否放行或者重新发放jwt)
let checkPermission = (req, res, next) => {
//若是跨域请求 首先会有一个试探请求 OPTIONS
if (req.method === 'OPTIONS') {
res.send({
"msg": "ok"
})
} else if (req.originalUrl === '/api/user/login') {
next();
} else if (req.headers.hasOwnProperty('token')) {
logger.info("token 验证", req.headers.token)
jwt.verify(req.headers.token, constant.secret, function(err,
decoded) {
if (err) {
//logger.error(err); //无效 刚过期(刷新token)
if (err.name === 'TokenExpiredError') { //过期
logger.error('token过期');
// 得到过期时间 若半小时以内 可以刷新token 即不需要重登录
let time = ((new Date().getTime() -
err.expiredAt.getTime()) / (1000 * 60)).toFixed(2)
if (time <= 30) {
logger.info('生成新的token返回前端'); //与登录一样 前端要
用新token
//根据code返回新token, 前端拿到新token再次发请求
res.send({
"code": "10001",
"token": "xxxxxx"
});
}
} else if (err.name === 'JsonWebTokenError') {
logger.error('token无效');
}
} else {
logger.info(JSON.stringify(decoded))
服务部署
mac
windows(xftp + xshell)
启动脚本
req.user = decoded; //将解密的数据保存在user属性中
next();
}
})
} else {
logger.info("没有token,无效请求")
res.send({
"msg": "没有token,无效请求"
})
}
}