欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue下axios拦截器token刷新机制的实例代码

程序员文章站 2022-03-25 15:43:31
//创建http.js文件,以下是具体代码: //引入安装的axios插件 import axios from 'axios' import router from '@...

//创建http.js文件,以下是具体代码:

//引入安装的axios插件
import axios from 'axios'
import router from '@/router';
import vue from 'vue'
const qs = require("qs");
let _this = new vue();
let islock = false;
let refreshsubscribers = [];
//判断token是否过期
function istokenexpired(token) {
 let expires_time = json.parse(token).expires_time;
 let curenttime = new date().gettime();
 if (curenttime >= expires_time) {
  return true;
 } else {
  return false;
 }
}
//获取token对象
function gettoken() {
 return localstorage.getitem("token");
}
//push所有请求到数组中
function subscribetokenrefresh(cb) {
 refreshsubscribers.push(cb)
}

//刷新请求(refreshsubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据)
function onrrefreshed(token) {
 refreshsubscribers.map(cb => cb(token))
}
//刷新token
function refreshtoken(config, token, resolve, reject) {
 let data = { refresh_token: json.parse(token).refresh_token };
 axios({
  method: "post",
  url: "xxxxxx/refreshtoken",//刷新token的接口
  headers: {
   "content-type": "application/x-www-form-urlencoded",
   "authorization": "basic b3jkzxitc2vydmvyojeymzq1ng=="
  },
  data: qs.stringify(data)
 }).then(res => {
  islock = false;//释放锁
  if (res.data.code === 101) {
   _this.$message.error('登录状态已失效,请重新登录。');
   localstorage.removeitem("token");
   router.push({
    path: "/login"
   });
   return;
  }

  let expires_time = new date().gettime() + parseint(res.data.data.expires_in * 0.8) * 1000;
  let token = json.parse(localstorage.getitem("token"));
  token.expires_time = expires_time;
  token.access_token = res.data.data.access_token;
  localstorage.setitem("token", json.stringify(token));

  config.headers.authorization = 'bearer ' + res.data.data.access_token;
  resolve(config);
  //执行数组里的函数,重新发起被挂起的请求
  onrrefreshed(res.data.data.access_token)
  //清空数组中保存的请求
  refreshsubscribers = []
 }).catch(err => {
  return err;
 });
}

function request(newoptions, resolve, reject) {
 axios({
  method: newoptions.method,
  url: newoptions.url,
  data: newoptions.type == "form" ? qs.stringify(newoptions.data) : newoptions.data,
  headers: newoptions.headers
 }).then(res => {
  if (res.status == 200) {
   //这里我们只需要获取返回的data中的数据即可
   resolve(res.data);
  } else {
   reject(res.data);
  }
 }).catch(err => {
  reject(err);
  _this.$message.error('服务异常!');
 })
}

axios.interceptors.request.use(
 config => {
  let token = gettoken();
  if (token) {
   //判断token是否过期,如果过期请求刷新token
   if (istokenexpired(token)) {
    //判断当前是否正在请求刷新token
    if (!islock) {
     islock = true;//islock设置true,锁住防止死循环。
     //使用promise等待刷新完成返回配置信息
     let refresh = new promise((resolve, reject) => {
      refreshtoken(config, token, resolve, reject);
     })
     return refresh;

    } else {
     //判断当前url是否是刷新token的请求地址,如果是直接下一步。
     if (config.url.indexof('/logined/refreshtoken') === -1) {
      //把请求(token)=>{....}都push到一个数组中
      let retry = new promise((resolve, reject) => {
       //(token) => {...}这个函数就是回调函数
       subscribetokenrefresh((token) => {
        config.headers.authorization = 'bearer ' + token
        //将请求挂起
        resolve(config)
       })
      })
      return retry

     } else {
      return config;
     }
    }

   } else {
    return config;
   }

  } else {
   return config;
  }
 }, error => {
  return promise.reject(error);
 });
const http = options => {
 return new promise((resolve, reject) => {
  const defaultoptions = {
   type: "json"
  };
  const newoptions = {
   ...defaultoptions,
   ...options
  };
  //headers默认传递json格式数据,这里也可以设置token,每次调用都会携带
if (localstorage.getitem("token")) {
    newoptions.headers = {
     // 'authorization': 'basic b3jkzxitc2vydmvyojeymzq1ng==',
     'content-type': newoptions.type == 'form' ? 'application/x-www-form-urlencoded;charset=utf-8' : 'application/json;charset=utf-8',
     'authorization': 'bearer ' + json.parse(localstorage.getitem("token")).access_token,
     ...newoptions.headers
    };
   } else {
    newoptions.headers = {
     'content-type': newoptions.type == 'form' ? 'application/x-www-form-urlencoded;charset=utf-8' : 'application/json;charset=utf-8',
     ...newoptions.headers
    };
   }
  request(newoptions, resolve, reject);
 })
};

//设置请求超时
axios.defaults.timeout = 30000
export default http

//在main.js下面挂载 http.js文件
import http from '@/utils/http.js';
vue.prototype.http = http;

//登录保存token信息接口

this.http({
      method: "post",
      url: "/xxxxx/user",
      type: "form",
      headers: { authorization:"basicb3jkzxitc2vydmvyojeymzq1ng==" },
      data: {}
     }).then(function(res) {
        let expires_time =
         new date().gettime() +
         parseint(res.data.token.expires_in * 0.8) * 1000;
         let token = res.data.token;
         token.expires_time = expires_time;
        localstorage.setitem("token", json.stringify(token));
    
      }).catch(function(err) {
       console.log(err);
      });        

//退出清空token
this.http({
    method: "get",
    url: "/xxxxx/logout",
    data: {}
   }).then(function(res) {
 localstorage.removeitem("token");
  }).catch(function(err) {
     console.log(err);
    });

总结

以上所述是小编给大家介绍的vue下axios拦截器token刷新机制的实例代码,希望对大家有所帮助