背景
Token 通常用于用户认证和权限管理,当 Token 过期时一般会重定向到登录页,用户的操作会受到影响,因此需要无感刷新。以下用双token实现。
原理
每次发起请求时,检查访问令牌的有效性。
如果访问令牌过期,暂停当前请求并使用刷新令牌获取新的访问令牌。
使用新的访问令牌重新发起之前被暂停的请求。
更新应用中的 Token 信息。
以上原理是其他博客里看到的描述,但是在他们的代码里,都没有暂停请求,只是存储了失败的请求。
vue+axios场景下实现无感刷新
// 创建axios实例
| 12
 3
 4
 
 | const service = Axios.create({baseURL,
 timeout: 30000
 })
 
 | 
// 新增请求拦截器,主要用于请求前带上token
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | service.interceptors.request.use(async config => {
 
 config.headers['token'] = getStorage('token')
 return config
 },
 error => {
 
 return Promise.reject(error)
 }
 )
 
 | 
// 新增响应拦截器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | service.interceptors.response.use(async (res) => {
 if (res.code === 100) {
 
 
 const methodMap = {
 get: $get,
 post: $post,
 put: $put,
 del: $del
 }
 
 const method = methodMap[res.config.method]
 const url = res.config.url
 let data = res.config.data
 
 
 await store.dispatch('system/execRefreshToken')
 
 return method(url, data)
 } else {
 ...
 }
 
 },
 err => {
 return Promise.reject(err)
 }
 )
 
 | 
// 刷新部分
如果多个接口用过期的token,都会进入此方法,为了防止重复调用刷新,设置了promise,能适用于大部分情况
注:但是这个promise只能在刷新时防止重复,试想如果有个接口(用了过期token的)响应很慢,在刷新完token后,promise置null了,才进入响应拦截器,这时就又会调用一遍刷新。
TODO:1.promise置null加个延迟,能防止大部分情况。2.刷新后再设置个变量,短时间内用来判断是否已经刷新
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | let promise = nullexecRefreshToken() {
 if(promise) return promise
 promise = new Promise((resolve, reject) => {
 const token = getStorage('token')
 const refreshToken = getStorage('refreshToken')
 const params = {
 token,
 refreshToken
 }
 $post(api.sysLoginRefreshToken, params).then(res => {
 setStorage('token', res.token)
 setStorage('refreshToken', res.refreshToken)
 resolve(res)
 }).catch(err => {
 reject(err)
 })
 })
 promise.finally(() => {
 promise = null
 })
 return promise
 }
 
 |