在vue中如何实现token续期(刷新token)
原因
最近公司项目有一个视频播放的功能,然后由于在测试环境登录时token过期时间较短导致一直在当前页面播放视频会出现token过期的现象,然后用户刷新会触发axios响应拦截器的操作退出系统。所以需要解决这个token过期的问题 ,以便在token过期前通过接口刷新token,让过期时间延长。
思路
那有了这个需求,就要说说解决思路了,一般来说,我们登陆成功的时候会通过账号密码来调用一个获取token的接口,此接口内会有token的过期时间以及一个refreshToken标识,该refreshToken则是用来刷新token的标识,然后呢我们可以通过判断token的过期时间与我们当前时间的差值来动态刷新,比如我们公司是过期之前半个小时来发送刷新token的请求。
解决方法
那思路有了就开始撸码呗,这个刷新token的请求放在哪里合适呢?然后发这个请求的时候会不会阻断页面的其他请求等等这些问题还需要咱们思考。本来我刚开始是准备放到router.beforeEach里面,每次刷新页面的时候判断时间差,但是这样的话属于看运气,没到时间的话不会发请求,而超出时间的话则会一刷新就退出系统。。。而且由于是视频播放一般也会停留许久,所以我就把请求放在axios的请求拦截器里了,每此法请求时判断时效性,播放视频时是采用轮训的方式发送播放记录,也刻意即时响应,nice!
好了 接下来放代码 各位刻意酌情参考
首先我们先获取到token和过期时间以及当前时间
/* 被挂起的请求数组 */
let refreshSubscribers = []
let isRefreshing = false // 是否有请求正在刷新token
/* push所有请求到数组中 */
function subscribeTokenRefresh(cb) {
refreshSubscribers.push(cb)
}
/* 刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据) */
function onRrefreshed(token) {
refreshSubscribers.map(cb => cb(token))
}
const token = localStorage.getItem('token')
const t = new Date().getTime() // 当前时间
const tokenExpTime = localStorage.getItem('tokenExpTime') // 过期时间
接下来判断token是否存在,因为在登录时是不需要token的,登录成功之后的接口才需要token,然后判断过期时间是否大于当前时间,是的话直接退出,否则判断是否在半小时内(我设的过期时间是半小时),是的话就挂起其他请求(可能你在刷新页面的时候token时效已经在半小时内,此时页面内有很多接口同时发起请求,则需要把这些请求挂起,只调用刷新token的请求),subscribeTokenRefresh方法则是这个作用,当发送完refreshToken的请求后,此时则把挂起的请求取出重新调用,onRrefreshed此方法则是起该作用,调用结束后,token就续期成功啦!!!
if (token) {
config.headers['Authorization'] = 'Bearer ' + token
if (tokenExpTime) {
// 已经过期 直接退出
if (tokenExpTime < t) {
store.dispatch('FedLogOut').then(() => {
router.push({ path: '/' })
})
// 判断token是否快到期 过期前半小时刷新 30 * 60 * 60 * 1000
} else if (tokenExpTime - 10 * 60 * 1000 < t && config.url.indexOf('refreshTokenAPI') === -1) {
// 是否在刷新
if (!isRefreshing) {
isRefreshing = true
const params = {
refreshToken: store.getters.refreshToken
}
// 刷新token
store.dispatch('refresh', params).then(res => {
isRefreshing = false
window.localStorage.setItem('tokenExpTime', new Date().getTime() + res.expiresIn * 1000)
onRrefreshed(token)
refreshSubscribers = []
return
}).catch(() => {
store.dispatch('FedLogOut').then(() => {
router.push({ path: '/' })
})
})
}
const retry = new Promise((resolve, reject) => {
/* (token) => {...}这个函数就是回调函数*/
subscribeTokenRefresh((token) => {
config.headers.Authorization = 'Bearer ' + token
/* 将请求挂起*/
resolve(config)
})
})
return retry
} else {
return config
}
}
} else {
return config
}
把新的过期时间存在本地继续同当前时间对比,每次到你设置的过期时间前则继续上述操作。
__以上就是我总结的如何在vue中刷新token的操作,若有更好的解决方法也希望可以互相讨论哈,喜欢的可以点赞,感谢 __