首先需要下载 jsonwebtoken包,用于在后端生成token,校验token
1.用户点击登录,在后端生成两个token,传给客户端进行保存。
//手机号登录
var access = "accessToken"
var refresh = "refreshToken"
router.post("/phoneLogin",async (req,res)=>{
var {phone} = req.body
var data = await LoginModel.find({phone:phone})
if(data.length > 0){
var accessToken = jwt.sign({ phone:phone }, access, { expiresIn: '10s' });
var refreshToken = jwt.sign({ phone:phone }, refresh, { expiresIn: '10h' });
res.send({
code:200,
accessToken:accessToken,
refreshToken:refreshToken,
msg:"登录成功"
})
}else{
res.send({
code:500,
msg:"账号不存在"
})
}
})
2.封装axios请求拦截器,将token添加到请求头中,以验证token的有效性。
// 创建一个axios实例
const instance = axios.create({
baseURL: 'http://localhost:3000',
})
// 请求拦截器
instance.interceptors.request.use(
(config) => {
// 从本地存储或 Cookie 中获取 access token
const accessToken = localStorage.getItem('accessToken')
// 将 access token 添加到请求头中
if (accessToken) {
config.headers['Authorization'] = `Bearer ${accessToken}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
3.后端验证token的时效性,并应用。
const jwt = require("jsonwebtoken")
var access = "accessToken"
const verifyAccessToken = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(403).json({ message: 'Unauthorized' });
}
jwt.verify(token, access, (err, user) => {
if (err) {
return res.status(403).json({ message: 'Invalid token' });
}
req.user = user;
next();
});
}
module.exports = { verifyAccessToken }
//测试无感刷新
const {verifyAccessToken} = require("../jwt/jwt")
router.get("/aaa",verifyAccessToken,async (req,res)=>{
res.send({
msg:"成功喽!"
})
})
4.前端封装响应拦截器,如果token失效了就发送刷新token的请求。
//响应拦截器
instance.interceptors.response.use(
(response) => {
//成功的响应
console.log(response.data);
return response;
},
async(error) => {
//失败的响应
console.log(error.response.status);
if(error.response.status == 401){
showToast('还未登录,请登录!');
return false
}
if (error.response.status === 403) {
// 尝试刷新 Token
try {
const {data:{newAccessToken,newrefreshToken}} = await instance.post('/lkx/refreshtoken', {
refreshToken: localStorage.getItem('refreshToken'),
});
localStorage.setItem('accessToken', newAccessToken);
localStorage.setItem('refreshToken',newrefreshToken)
console.log("token刷新啦!");
// 重新发送原始请求
return instance(error.response.config);
} catch (err) {
// 刷新 Token 失败,跳转到登录页
// 你可以根据具体情况执行其他操作
// 清除 Token
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
// 跳转到登录页
// window.location.href = '/login';
return Promise.reject(err);
}
}
return Promise.reject(error);
}
);
5.后端判断刷新令牌的时效性,如果刷新令牌失效了就返回错误响应,如果没有失效,就刷新token。
//刷新令牌
router.post("/refreshtoken",async(req,res)=>{
const refreshToken = req.body.refreshToken;
if (!refreshToken) {
return res.status(401).json({ message: 'Invalid refresh token' });
}
jwt.verify(refreshToken, refresh, (err, user) => {
if (err) {
return res.status(401).json({ message: 'Invalid refresh token' });
}
// 生成新的 Access Token
const newAccessToken = jwt.sign({phone:user.phone}, access, { expiresIn: '10s' });
const newrefreshToken = jwt.sign({ phone:user.phone }, refresh, { expiresIn: '10h' });
res.send({ newAccessToken,newrefreshToken });
});
})
ok啦!!!