为了账号安全,请及时绑定邮箱和手机立即绑定

axios定时刷新Token

好记性不如烂笔头

做项目时遇到的一个头疼的问题,也是首次接触,只能自己摸索,
在网上查了好多资料,有的都是写了重要步骤,没有完整的代码,所以花了我一周的时间去弄这个问题,也查找了很多资料,然后深入学习axios;
1.定时刷新token,简而言之就是隔一段时间去刷新一次token,当然前提是原来的token还没有过期的情况下,才能去刷新,否则直接跳回登录首页;

import axios from 'axios'; // 引入axios
// 创建实例时设置配置的默认值 
// 注意这个实例 在之后的api请求接口时全部用的是server
let service = axios.create({
  baseURL: 'http://xxxxx
});
// 是否正在刷新的标志
window.isRefreshing = false;
// 存储请求的数组
let refreshSubscribers = [];

/*将所有的请求都push到数组中*/
function subscribeTokenRefresh(cb) {
  refreshSubscribers.push(cb);
}

// 数组中的请求得到新的token之后自执行,用新的token去请求数据
function onRrefreshed(token) {
  refreshSubscribers.map(cb => cb(token));
}
// 刷新token的过期时间判断
function isRefreshTokenExpired() {
  let oData = loadTimeStamp(); // 这是在登陆时候保存的时间戳
  let nDta = new Date().getTime();
  let stamp = nDta - oData;
  let minutes = parseInt((stamp % (1000 * 60 * 60)) / (1000 * 60));
  return minutes >= 30? true : false;
}

刷新token

function getRefreshToken() { // 刷新token 注意这里用到的service
    return service.post(proApi.api.refreshUserTokenApi)
      .then((res) => {
        return Promise.resolve(res.data)
      }) 
}

axios 拦截器,主要实在请求时判断token是否即将过期,然后请求刷新token

/*请求拦截器*/
service.interceptors.request.use(
  config => {
    const authTk = loadUserToken(); // 本地保存的token
    /*判断token是否存在*/
    if (authTk) {
      /*在请求头中添加token类型、token*/
      config.headers.Authorization = loadUserKey() + ' ' + loadUserToken();

      config.url =config.url+'?t='+(new Date()).getTime().toString(); // 清楚缓存
      /*判断token是否将要过期 */
      if (isRefreshTokenExpired() && (config.url.indexOf('user/refresh') === -1 || config.url.indexOf('bidder/refresh') === -1)) {
        if (!window.isRefreshing) {  // /*判断是否正在刷新*/
          window.isRefreshing = true;
          /*发起刷新token的请求*/
          getRefreshToken().then(res => {
            window.isRefreshing = false;
            saveUserToken(res.access_token);
            saveUserKey(res.token_type);
            saveTimeStamp(new Date().getTime());
            /*执行数组里的函数,重新发起被挂起的请求*/
            config.headers.Authorization = res.token_type + ' ' + res.token;
            onRrefreshed(res.access_token);
            /*执行onRefreshed函数后清空数组中保存的请求*/
            refreshSubscribers = []
          }).catch(err => {
            /*清除本地保存的*/
            clearAllCache();
            window.location.href = '#/user/login'
          });
          /*把请求(token)=>{....}都push到一个数组中*/
          let retry = new Promise((resolve, reject) => {
            /*(token) => {...}这个函数就是回调函数*/
            subscribeTokenRefresh((token) => {
             // config.headers.common['Authorization'] = 'bearer ' + token;
              config.headers.Authorization = 'bearer ' + token;
              /*将请求挂起*/
              resolve(config)
            })
          });
          return retry
        }
        return config
      } else {
        return config
      }
    } else {
      return config
    }
  },
  /*错误操作*/
  err => {
    return Promise.reject(err)
  }
);

axios拦截器response对过期token拦截,然后跳转登录界面

service.interceptors.response.use(response=>{
  return response;
  },
  error => {
    let errorResponse = error.response;
    if (errorResponse.status === 401) {
      Message.error('token已过期,请重新登录'); // Message是element-ui的一个组件
      window.location.href = '#/login';
      clearAllCache(); // 清空所有缓存
    }
    return Promise.reject(error);
  });

export default service;

在以上实例化axios之后,在其他api请求的时候,使用的形式如下

import service from '@/assets/js/axios.config';
service.post(proApi.api.getListApi, data)
    .then((res) => {
      if (res.data.code == ERR_OK) { // ERR_OK 是自己设置的统一错误代码
        return Promise.resolve(res.data)
      }
    })
点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
7
获赞与收藏
225

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消