1.了解token相关的概念
1.1 JWT标准的token有如下三部分
hearder(头部)、 payload(数据)、 signature(签名)
生成的标准的token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInVzZXJfaWQiOjEsImlhdCI6MTU5NDI2MjQ5NSwiZXhwIjoxNTk0MzQ4ODk1fQ.1MJ_MAFgpBjOjpggj69Xz8F_evBcMAenRK_7a8fdVrc
1.2 token验证的基本流程
1.服务端收到请求,去验证用户名与密码
2.验证成功后,服务端会签发一个token,再把这个token发送给客户端
3.客户端收到token以后可以把它存储起来,可以放在Cookie或者LocalStorage本地存储里
4.客户端每次向服务端请求资源的时候需要带着服务器签发的token
5.服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据,如果验证失败就返回。
2.使用token的过程(以登录为实例)
2.1安装依赖包
依赖包:jsonwebtoken
作用:生成token与验证
npm install jsonwebtoken --save
npm install express-jwt@6.1.1
jsonwebtoken的两个api:
生成token的方法sign
验证token的方法verify
express-jwt的作用:
验证token是否过期并规定哪些路由不需要验证 (具体代码下面会写)
express-jwt安装的时候注意版本 6.1.1(不然可能会报错)
2.2 token express后端相关代码
定义生成token和获取token的函数
/token/token.js
const jwt = require('jsonwebtoken');
// 密钥
const jwtSecret = 'wangwushan'; //签名
//登录接口 生成token的方法
// setToken携带的参数及参数的数量自定义
const setToken = function (uname) {
return new Promise((resolve, reject) => {
//expiresln 设置token过期的时间
//{ user_name: user_name, user_id: user_id } 传入需要解析的值( 一般为用户名,用户id 等)
// const token = jwt.sign({ user_name: user_name }, jwtSecret, { expiresIn: '24h' });
const token = jwt.sign({ uname: uname }, jwtSecret, { expiresIn: '10s' });
// 注意:expiresIn 过期事件,可以调整为24h后过期,10s太短了
resolve(token)
})
}
//各个接口需要验证token的方法
const getToken = function (token) {
return new Promise((resolve, reject) => {
if (!token) {
console.log('token是空的')
reject({
error: 'token 是空的'
})
}
else {
// 验证token
var info = jwt.verify(token.split(' ')[1], jwtSecret);
resolve(info); //解析返回的值(sign 传入的值)
}
})
}
module.exports = {
setToken,
getToken
}
2.3解析token,验证token
app.js
const express = require("express")
const app = express()
//express跨域
const cors = require("cors")
// 生成token和验证token是否正确的函数
const vertoken=require('./token/token')
//验证token是否过期,并规定哪些路由不用验证token
const expressJwt=require('express-jwt')
const bookRouter = require("./router/bookRouter")
const userRouter = require("./router/userRouter")
app.use(cors())
//=============================================验证token
//解析token获取用户信息
app.use(function(req, res, next) {
let token = req.headers['authorization'];
if(token == undefined){
next();
}else{
vertoken.getToken(token).then((data)=> {
console.log('解析后的token',data);
req.data = data;
next();
}).catch((error)=>{
next();
})
}
});
//验证token是否过期并规定那些路由不需要验证
app.use(expressJwt({
secret:'dkfjdjfkdfdfd',
// 加密算法
algorithms:['HS256']
}).unless({
path:['/login'] //不需要验证的接口名称
}))
/*
注意:直接安装使用expressJwt的时候,会在运行的时候报错
因为express-jwt升级了,后以前的用法应该是不同了
只需要将pakage.json中的express-jwt版本改为6.1.1,重新npm i 即可使用。
*/
//token失效返回信息
app.use(function(err,req,res,next){
if(err.status==401){
res.status(401).send('token失效11111111')
}else{
next()
}
})
app.use(bookRouter)
app.use(userRouter)
app.listen(3000, () => {
console.log("服务器已开启在3000端口");
})
2.4 登录接口
/router/usersRouter.js
let express = require("express");
let userRouter = express.Router();
const db = require("../utils/db")
const vertoken = require("../utils/token")
// 登陆操作
userRouter.post('/login', (req,res)=>{
let {uname,pwd} = req.body;
console.log(uname,pwd);
let sql = `select * from login where uname = '${uname}' and pwd = '${pwd}'`
db.base(sql, null, (result) => { // result 数组包对象格式
console.log(result);
if (result.length) {
//==============================================调用生成token的方法
vertoken.setToken(uname).then(token => {
data = {
code: 0,
message: '登录成功',
token: token
//前端获取token后存储在localStroage中,
//**调用接口时 设置axios(ajax)请求头Authorization的格式为`Bearer ` +token
}
res.send(data)
})
} else {
data = {
code: 1,
msg: '登录失败 '
}
res.send(data)
}
});
});
module.exports = userRouter
3. token vue前端相关代码
3.1登录后获取token
在登录页面 login.index里
axios.post("http://localhost:3000/login")
.then((res) => {
console.log('login返回的数据');
if (res.data.code == 0) {
alert('登录成功')
//存储token
sessionStorage.setItem("token",res.data.token)
}
});
3.2前端请求携带token
再次向服务端发送请求时携带token
methods: {
async getList() {
let token = localStorage.getItem("token");
if (token) {
let res = await axios.get("http://localhost:5000/cart", {
headers: {
Authorization: "Bearer " + localStorage.getItem("token"),
},
});
this.list = res.data.list;
} else {
alert("请登录");
}
},
},