场景:在往常的接口中我们通过从后端获取的token来进行身份识别,并且获取一些登录后的才能获取的一些数据,那么这个token有效期很短的时候,那么总不能让用户再登录一次来刷新token,所以我们需要提供一项操作,--------无感刷新(这个一般用在单点登录的时候)
首先呢用户第一次登录的时候,从后端获取两个token,一个是短期token 一个是长期token,用户之后获取一些权限性的数据时候是在请求头携带短期token的,这个长期token只有一个作用就是在短期token失效的时候来当作参数发给后端取更新短期token的。更新短期token的这个会单独设置一个接口。
下面是代码 无感刷新前端主要是逻辑代码,难度不大,下面的代码仅供参考
下面文件利用的tool.js的工具函数就是单纯从localStorage去获取值的操作,代码我就不贴了。
// axios请求拦截器页面
import { setToken, setRefreshToken, getToken } from './tools.js'
import { refreshToken, isRefreshRequest } from './api.js'
const ins = axios.create({
baseURL: 'http://xxxxxxxxx',
headers: {
Authorization:
}
});
ins.interceptors.response.use(async (res) => {
if (res.headers.authorization) {
const token = res.headers.authorization.replace('Bearor', '')
setToken(token)
ins.defaults.headers.Authorization = `Bearor${token}`
}
if (res.headers.refreshtoken) {
const refreshtoken = res.headers.refreshtoken.replace('Bearor', '')
setRefreshToken(refreshtoken)
}
if (res.data.code === 401 && !isRefreshRequest(res.config)) { //如果token失效并且不是更新token的接口时
// 用长token去换短token
const isSuccess = await refreshToken()
if (isSuccess) { //获取新token成功的话
// 有新的token后,重新请求
console.log('重新请求');
res.config.headers.Authorization = `Bearor${getToken()}` //重新请求前需要将更新后的新token更换掉之前无效的token,不然会死循环
const resp = await ins.request(res.config)
return resp
} else {
// 刷新失效,跳转登录页
console.log('跳转到登录页');
}
}
return res.data
})
export default ins;
//api文件页面
import request from './request'
import { getRefreshToken } from './tools.js'
export function login() {
return request.post('/login')
}
export function reqProtected() {
return request.post('/protected')
}
let promise;
export function refreshToken() {
if (promise) { //这样操作是为了防止一种场景:在token失效的时候,同时调用了多个接口,这多个接口因为token失效 所以会执行多次更新token请求的操作。这个操作就是为了在同一时间点只会执行一次更新token
return promise
}
promise = new Promise(async (resolve, reject) => {
console.log('更新token');
const resp = await request.get('/refreshToken', {
headers: {
Authorization: `Bearor${getRefreshToken()}`
},
__isRefreshToken: true, //添加一个自定义属性判断 用来识别该请求是刷新token用的
})
if (resp.code === 401) {
resolve(false)
} else {
resolve(true)
}
})
promise.finally(() => {
promise = null
})
}
//判断某个请求是否包含__isRefreshToken属性 进而判断是否是更新token的接口请求
export function isRefreshRequest(config) {
return !!config.__isRefreshToken
}