token刷新介绍
- 单token,用于登录判断
- toekn过期自动刷新
- 拒绝一切前端判断token
- 数据库存储token最后刷新时间与刷新次数
- 刷新次数上限20次
- 未登录3天需重新登录来刷新token
token刷新规则
- token过期自动刷新,并累加刷新次数,上限刷新20次,超过20次无法刷新token,需重新登录
- 若最后刷新时间是3天前,也就是3天没有登录过,无法刷新token,需重新登录
前端代码
Axios的封装
- 封装的作用
- 发起token更新请求时,若有其它请求,利用promise将请求先挂起,并push到一个数组
- token请求返回结果后,再重新发起请求,执行push的数组
- 后端状态码为
456
表示token过期
scr/api/axios.js
import axios from 'axios'
import {
storeToRefs } from 'pinia'
import useUserInfoStore from '@/stores/userInfo'
// 创建一个 axios 实例
const service = axios.create({
timeout: 5000,
})
let tokenUpdateing = false,//token是否处于更新中
reqLists = []//更新token时请求的队列
// 请求拦截器
service.interceptors.request.use(config => {
// 带上token发起请求
const userInfoStore = useUserInfoStore(),
{
auth } = storeToRefs(userInfoStore)
auth && (config.headers.auth = auth.value)
return config
}, error => {
// return error
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(async res => {
const {
statu } = res.data,
{
url, method, params } = res.config
// token过期
if (statu === 456) {
const reqConfig = {
url, method, params }
// 更新token中,先将请求配置push到reqLists,token更新完成后再重新发起请求
if (tokenUpdateing === true) {
//token更新中,将请求挂起
return new Promise(resolve => {
// token更新中,push请求 ,不push相同的请求
const findRepeat = reqLists.findIndex(val => JSON.stringify(val) === JSON.stringify(reqConfig))
if (findRepeat === -1) reqLists.push(reqConfig)
resolve(service(reqConfig))
})
// 开始更新token
} else {
tokenUpdateing = true
const uid = 6666,//用户id
{
statu, msg } = await service({
//向后端请求新token
url: `/api/updatetoken`,
params: {
uid,
sign: MD5(uid + 'usersid')//md5签名,防止篡改请求
}
}),
userInfoStore = useUserInfoStore()//重点:pinia仓库,作用:存储token
// token请求成功
if (statu === 200) {
// 请求成功,更新token到pinia
userInfoStore.$patch(state => {
state.auth = msg
})
} else {
// token更新失败,重置pinia仓库
userInfoStore.$reset()
}
//token更新完成 ——> 重新发起请求
reqLists.forEach(it => service(it))
reqLists = []//清空请求队列
tokenUpdateing = false //关闭token更新
// 重新发起请求
return service(reqConfig)
}
}
return res.data
}, error => {
Promise.reject(error)
})
export default service
store(pinia持久化存储)
- pinia官网 - https://pinia.web3doc.top/core-concepts/state.html#%E8%AE%BF%E9%97%AE-%E2%80%9Cstate%E2%80%9D
- pinia-plugin-persistedstate (pinia持久化存储库)- https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/config.html
scr/store/store.js
import {
defineStore } from 'pinia'
const useUserInfoStore = defineStore('userInfo', {
state: () => {
return {
userName: null,
logined: false,//是否登录
uid: null,
jianjie: null,
auth: null,//登录的token
showLoginForm: false,//显示登录/注册表单
}
},
persist: {
key: 'userInfo',
paths: ['auth'],
}
})
export default useUserInfoStore