vue中使用axios 无痛刷新token,替换旧token

22 篇文章 1 订阅
1 篇文章 0 订阅

需求:最近项目有个需求,后台返回token之后,过一段时间就会过期,为了让用户无感知操作,前端需要利用旧token 去请求新token,请求成功之后,用新token 接着进行接口调取。

关于刷新token的问题,网上查了很多,有很多解决方案,要和后台的同学商量好,总之目的就是替换token,并且让用户无感操作。

 

我的思路为利用axios 的拦截器,判断如果返回是401 ,那么就利用旧token去请求新token,完成之后再继续请求之前未成功的接口和  缓冲起来的接口(见下文)。

 

问题一:token 过期之后返回401 ,利用旧token 获取到新 token 之后,覆盖本地token,如何接着调取前面失败到接口。解决办法为

axios.request(config);  注意需要return ,见下文,这样就会重新走一遍axios 请求

问题二:在 return axios.request(config) 之前,注意需要在config 里面把token 替换掉,因为config 里面的token是之前过期的。如有其余需要替换的,按实际情况来做。类似如下:

error.config.headers.Authorization = res.data.Data;  (res.data.data 为新返回的token)

问题三:如果token 过期后,刚好需要请求多个接口,请求接口为异步,此时就会出现多次调取刷新token的接口。当第一次调取刷新token接口时,还没有返回新token,此时,第二个接口又用过期token请求,导致会出现多吃请求的问题解决办法为设置一个变量,判断是否刷新,如果正在刷新,就把这个接口缓冲起来,等到请求成功之后,再遍历缓冲起来的接口,重新请求。

问题四:缓冲起来的接口,遍历请求的时候,这里也会有异步的问题,我们用promise 来解决。

完整代码如下:

// 是否正在刷新
let isRefreshing = false;
// 重试队列 每一项都是一个待执行待函数
let requests: any[] = [];



// 401: token 过期 请求新token ,
        case 401:
            if (!isRefreshing) {
                isRefreshing = true;
                // 获取旧 token
                let token = sessionStorage.getItem('token');
                // 刷新token
                axios.post(`${base.url}System/RefreshToken?id=${token}`).then(res => {
                    // 重新设置token
                    sessionStorage.setItem('token', res.data.Data);
                    // 重新请求接口 前过期的接口
                    error.config.headers.Authorization = res.data.Data;
                    error.config.headers.withCredentials = true;
                    requests.length > 0 && requests.map((cb) => {
                        cb();
                    });
                    requests = [];  //注意要清空
                    return axios.request(error.config);
                }).catch(err => {
                    Message('刷新token失败,请重新登录');
                    toLogin();
                }).finally(() => {
                    isRefreshing = false;
                })
            } else {
                // 正在刷新token ,把后来的接口缓冲起来
                return new Promise((resolve) => {
                    requests.push(() => {
                        error.config.headers.Authorization = sessionStorage.getItem('token');
                        error.config.headers.withCredentials = true;
                        resolve(axios.request(error.config));
                    });
                })
            }
            break;

 

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值