最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【axios】不可不知的axios无感刷新token

    正文概述 掘金(菩提谛听)   2021-07-17   735

    背景

    最近项目用户登录页面处于安全考虑,登录之后的access_token并非永久有效而是有实效性了,因此 需要在用户登录之后token失效的情况下进行access_token的无感知刷新,也既是需要前端在access_token失效时调用一次refresh API使得access_token再次有效,而不影响用户的使用体验。

    需求拆解

    用户登录成功之后API会将{ access_token: '', refresh_token: '', expired: '' }返回,那就可以在用户发起一个请求时,判断access_token是否过期,过期就刷新access_token。首先判断access_token过期可以在请求之前根据expired判断,也可以在请求结果回来之后判断,问题的难点其实是指如何在多个请求进来时将这些请求暂存下来,然后在refresh之后在做请求场景还原。

    实现思路

    针对需求拆解主要需要解决两个问题,一是失效判断,二是多个请求还原,具体解法如下:

    1. 失效判断:(1)请求前根据expired的过期时间进行判断,但这种操作是不可靠的,因为时间是可修改的,所以不采用该方法;(2)根据请求结果判断access_token过期,然后进行刷新操作,然后在进行一次请求。
    2. 多请求的场景还原:当同时有多个过期请求进来时,需要避免多次refresh的请求,设置一个标志位,当已经有refresh的操作在进行时,再进来的请求进行挂起(此时可以利用Promisepending状态做文章),等待refresh成功之后在进行请求。

    伪代码实现如下

    import axios, { AxiosRequestConfig } from 'axios';
    
    interface IRequestConfig {
       tokenInfoKey: string; // 由于登录之后的 token 数据时存在 localstorage 需要键值
       onRefreshError: VoidFunction;
    }
    
    interface ITokenInfo {
        access_token: string;
        refresh_token: string;
        expired: string;
    }
    
    class Request {
      private config: IRequestConfig = {};
      private tokenInfo: ITokenInfo | null = null;
      private isRefreshing: boolean = false;
      private needRetryRequest = [];
      constructor (config: IRequestConfig) {
         const { tokenInfoKey } = config;
         this.tokenInfo = JSON.parse(localStorage.getItem(tokenInfoKey));
         this.config = config;
      }
      
      refreshAccessToken (onSuccess: VoidFunction) {
          return axios.request<ITokenInfo>({
              url: '',
              method: '',
          })
              .then((res) => {
                  localStorage.setItem(this.config.tokenInfoKey, res.data);
                  onSuccess();
              })
              .catch(() => {
                  this.needRetryRequest = [];
              });
      }
      
      request (config: AxiosRequestConfig) {
         if (this.isRefreshing) {
             return new Promise((resolve) => {
                 this.needRetryRequest.push(async () => await resolve(axios));
             });
         }
         return axios
           .request(config)
           .then(res => {
               return res.data;
           })
           .catch(e => {
               // 假设 401401 定义需要 refresh
               const code = 401401;
               const { status } = e.response;
               if (status === code) {
                   this.isRefreshing = true;
                   this.refreshAccessToken(() => {
                       Promise.all([() => this.request(config), ...this.needRetryRequest].map(cb => cb()));
                   });
               }
           })
           .finally(() => {
               this.isRefreshing = false;
           });
      }
    }
    

    起源地下载网 » 【axios】不可不知的axios无感刷新token

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元