需求
当token过期的时候,刷新token,前端需要做到无感刷新token,即刷token时要做到用户无感知,避免频繁登录。实现思路
方法一
后端返回过期时间,前端判断token过期时间,去调用刷新token接口
缺点:需要后端额外提供一个token过期时间的字段;使用了本地时间判断,若本地时间被篡改,特别是本地时间比服务器时间慢时,拦截会失败。
方法二(可行)
写个定时器,定时刷新token接口
缺点:浪费资源,消耗性能,不建议采用。
方法三 (推荐)
在响应拦截器中拦截,判断token 返回过期后,调用刷新token接口
思考:
我在遇到同样问题的时候也是考虑了两种方法,一种是定时刷新一种是过期时刷新。 但是我选择了定时刷新的方案。 假如token 的过期时间是5分钟,那么在高频率使用的情况下(每秒访问接口)每隔5分钟就会刷新一次token。如果web端有大屏展示页面的话,过期刷新的方案跟定时刷新的方案调用的token次数其实一样。但过期刷新的时候可能会阻碍接口的请求,导致每隔5分钟会出现一次接口变慢的情况。 测试下发现,用定时刷新的方案并不会浪费资源,唯一的代价就是需要运行一个定时器。
后端每个需要token的接口,都返回token的失效时间指的是定时器的时间也是后端返回token失效的时间
实现:
axios的基本骨架,利用service.interceptors.response进行拦截
importaxiosfrom'
axios'service.interceptors.response.use(response=>
{
if(response.data.code ===409) {
returnrefreshToken({
refreshToken:localStorage.getItem('refreshToken'),token: getToken() })
.then(res=> {
const{ token } = res.data
setToken(token)
response.headers.Authorization =`${token}`}).catch(err=> {
removeToken()
router.push('/login')
returnPromise.reject(err)
}) }
return response && response.data },(error) =>{
Message.error(error.response.data.msg)
returnPromise.reject(error)
})