Axios token刷新,拦截器设置

此项目是用vue做的管理报表系统,代码中的“quasar”是基于vue的框架
需求:出于安全性考虑,每次发起请求需要在header里带上token,并设置过期时间,在过期时间内重新请求可以刷新token,使用户不必被强制退出重新登录。
login页面逻辑: 登录成功之后存储token过期时间、token

    window.localStorage.setItem(this.$store.state.common.keyToken, token)
    window.localStorage.setItem(this.$store.state.common.tokenExpire, expire)

axios.js

  import axios from 'axios';
    import { Notify } from 'quasar';
    // 是否正在刷新的标志
    let isTokenRefreshing = false;
    //存储请求的数组
    let subscribesArr = [];
    // 请求push到数组中
    function subscribesArrRefresh(cb) {
      subscribesArr.push(cb);
    }
    // 用新token发起请求
    function reloadSubscribesArr(newToken) {
      subscribesArr.map(cb => cb(newToken));
    }

判断token是否过期

     //判断当前时间是否超过token过期时间
      function isTokenExpire(serverTokenExpire) {
          return getUTCTime(new Date()) >= getUTCTime(new Date(serverTokenExpire));
        }
        // 获取UTC时间
        function getUTCTime(now) {
          let year = now.getUTCFullYear();
          let month = now.getUTCMonth();
          let date = now.getUTCDate();
          let hours = now.getUTCHours();
          let minutes = now.getMinutes();
          let seconds = now.getUTCSeconds();
          let ms = now.getUTCMilliseconds();
          return Date.UTC(year, month, date, hours, minutes, seconds, ms);
        }

axios拦截器设置,判断token是否过期,过期则发起刷新token请求

    axios.interceptors.request.use((config) => {
        config.headers.common.AppCode = window.sessionStorage.getItem(store.state.common.AppCode);
        config.headers.common.MenuCode = window.sessionStorage.getItem(store.state.common.MenuCode); 
        let token = window.localStorage.getItem(store.state.common.keyToken);
        if (token) {
          config.headers.common.Authorization = store.state.common.tokenPre + token;
        }
        let serverTokenExpire = window.localStorage.getItem(store.state.common.tokenExpire);
        if (config.url.includes(Vue.prototype.$URLS.login)) {
          return config;
        }
        // 判断token是否过期
        if (serverTokenExpire && isTokenExpire(serverTokenExpire) && !config.url.includes(Vue.prototype.$URLS.refreshToken)) {
        // 判断token是否已经刷新过
          if (!isTokenRefreshing) {
            isTokenRefreshing = true;
        // 请求刷新token
            Vue.prototype.$axios.get(Vue.prototype.$URLS.refreshToken).then(({ data: { token, expire } }) => {
              isTokenRefreshing = false;
              window.sessionStorage.setItem(store.state.common.keyToken, token);
              window.sessionStorage.setItem(store.state.common.tokenExpire, expire);
              reloadSubscribesArr(token);
            }).catch(err => {
            // 请求失败,清空缓存,返回登录页
              isTokenRefreshing = false;
              subscribesArr = [];
              window.sessionStorage.clear();
              window.localStorage.clear();
              router.push('/login');
            });
          }
          let retry = new Promise((resolve, reject) => {
            subscribesArrRefresh((newToken) => {
              config.headers.Authorization = store.state.common.tokenPre + newToken;
              resolve(config);
            });
          });
          return retry;
        } else {
          return config;
        }
      }, (err) => {
        Notify.create({
          message: '错误的传参',
          color: 'negative',
          timeout: 5000,
          position: 'top'
        });
        return Promise.reject(err);
      });

response设置

axios.interceptors.response.use((res) => {
    // console.log(res.config.url + ' : ' + res.status)
    if (res.data == null) return Promise.resolve(res);
    let msg = res.data.message;
    if (msg == null || msg === '') {
      return Promise.resolve(res);
    } else {
      Notify.create({
        message: msg,
        color: 'negative',
        timeout: 5000,
        position: 'top'
      });
      return Promise.reject(res);
    }
  }, (err) => {
    let status = 0, msg = '';
    if (err && err.response) {
      status = err.response.status;
      msg = err.response.data.message;
    }

    // 捕捉token过期时,跳转到登录页
    if (status === 401) {
      if (msg !== null || msg !== '') {
        msg = msg.toLocaleLowerCase().includes('expired') ? '登录过期,请重新登录。' : msg;
        Notify.create({
          message: msg,
          color: 'negative',
          timeout: 5000,
          position: 'top'
        });
      } else {
        Notify.create({
          message: '',
          color: 'negative',
          timeout: 5000,
          position: 'top'
        });
      }
      window.sessionStorage.clear();
      router.push('/login');
      return;
    }

    if (msg === '') {
      msg = '网络异常';
    }
    Notify.create({
      message: msg,
      color: 'negative',
      timeout: 5000,
      position: 'top'
    });
    return Promise.reject(err);
  });
}

[参考](http://www.imooc.com/article/details/id/28155)

Logo

前往低代码交流专区

更多推荐