Token令牌的流程
- 服务端在收到用户的登录请求的时候,验证用户名和密码
- 验证成功之后,服务端会生成一个
Token
令牌,并把这个Token
发送给客户端 - 客户端收到Token之后,可以把它存储在
LocalStorage
中 - 客户端在每次使用
axios
发起请求的时候,可以使用请求拦截器把本地存储的Token
放在请求头中发送给服务端 - 服务端收到请求之后,验证请求头中的
Token
如果验证成功就返回数据,
使用NodeJS生成token
生成Token需要安装两个依赖包
-
npm i jsonwebtoken -S
jsonwebtoken
有两个方法
sign
生成token
verify
验证token -
npm i express-jwt -S
验证token
是否过期,并规定那些路由接口不需要验证
Token的组成
完整的token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ0b20iLCJ1c2VyX2lkIjoiNDU2IiwiaWF0IjoxNjIzMzczOTQzLCJleHAiOjE2MjM0NjAzNDN9.FDSYIP9j7bWQl9ORuMp9EyqNq8neiKwaJeD_LvlQfpc
可以看到token由用"."分隔的三部分组成
- heade(头部)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 是经过base64编码之后的结果
格式:
//默认是哈希256加密
{"alg":"HS256","typ":"JWT"}
- payload(载荷)
eyJ1c2VyX25hbWUiOiJ0b20iLCJ1c2VyX2lkIjoiNDU2IiwiaWF0IjoxNjIzMzczOTQzLCJleHAiOjE2MjM0NjAzNDN9
也是通过base64
编码之后的结果
格式:
{"user_name":"tom","user_id":"456","iat":1623373943,"exp":1623460343}
在你加密的时候设置的字段,注意不要把敏感信息设置进去,这里做测试而已。
- signature(签名)
FDSYIP9j7bWQl9ORuMp9EyqNq8neiKwaJeD_LvlQfpc
这个不是base64
编码,而是经过加密之后的数据,需要密钥才行。
使用token
新建token.js
var jwt = require('jsonwebtoken');
var jwtScrect = 'hello_token'; //签名
//登录接口 生成token的方法
var setToken = function (user_name, user_id) {
return new Promise((resolve, reject) => {
//expiresln 设置token过期的时间
//{ user_name: user_name, user_id: user_id } 传入需要解析的值( 一般为用户名,用户id 等)
const token = jwt.sign({ user_name: user_name, user_id: user_id }, jwtScrect, { expiresIn: '24h' });
resolve(token)
})
}
//各个接口需要验证token的方法
var getToken = function (token) {
return new Promise((resolve, reject) => {
if (!token) {
console.log('token是空的')
reject({
error: 'token 是空的'
})
}
else {
//第二种 改版后的
var info = jwt.verify(token.split(' ')[1], jwtScrect);
resolve(info); //解析返回的值(sign 传入的值)
}
})
}
module.exports = {
setToken,
getToken
}
在server.js中
//引入插件
var vertoken=require('./utils/token')
var expressJwt=require('express-jwt')
//验证token是否过期并规定那些路由不需要验证
app.use(expressJwt({
secret:'zgs_first_token',
algorithms:['HS256']
}).unless({
//用户第一次登录的时候不需要验证token
path:['/login'] //不需要验证的接口名称
}))
//解析token获取用户信息
app.use(function(req, res, next) {
var token = req.headers['authorization'];
if(token == undefined){
return next();
}else{
vertoken.getToken(token).then((data)=> {
req.data = data;
return next();
}).catch((error)=>{
return next();
})
}
});
//token失效返回信息
app.use(function(err,req,res,next){
if(err.status==401){
// return res.status(401).send('token失效')
//可以设置返回json 形式
res.json({status:401,message:'token失效'})
}
})
在用户登录接口中设置token
var vertoken = require('../utils/token')
//验证用户名和密码成功之后调用生成token的方法
vertoken.setToken(name, email).then(token => {
console.log(token);
res.end(JSON.stringify({
code: 200,
message: '登录成功',
token: token
//前端获取token后存储在localStroage中,
//**调用接口时 设置axios(ajax)请求头Authorization的格式为`Bearer ` +token
}))
在postman
测试