当前位置: 移动技术网 > IT编程>开发语言>JavaScript > vue下axios拦截器token刷新机制的实例代码

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

2020年03月09日  | 移动技术网IT编程  | 我要评论

//创建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刷新机制的实例代码,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网