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


Posted in Javascript onJanuary 17, 2020

//创建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刷新机制的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
JS实现的论坛Ajax打分效果完整实例
Oct 31 Javascript
继续学习javascript闭包
Dec 03 Javascript
JavaScript中Window对象的属性及事件
Dec 25 Javascript
jQuery操作Table技巧大汇总
Jan 23 Javascript
javascript时间戳和日期字符串相互转换代码(超简单)
Jun 22 Javascript
再次谈论Javascript中的this
Jun 23 Javascript
Javascript实现运算符重载详解
Apr 07 Javascript
官方推荐react-navigation的具体使用详解
May 08 Javascript
对vue下点击事件传参和不传参的区别详解
Sep 15 Javascript
Vue核心概念Getter的使用方法
Jan 18 Javascript
vue-cli3单页构建大型项目方案
Apr 07 Javascript
Node.js利用Express实现用户注册登陆功能(推荐)
Oct 26 Javascript
js布局实现单选按钮控件
Jan 17 #Javascript
vue 查看dist文件里的结构(多种方式)
Jan 17 #Javascript
JavaScript数组去重实现方法小结
Jan 17 #Javascript
JS面向对象之多选框实现
Jan 17 #Javascript
JavaScript基于面向对象实现的无缝滚动轮播示例
Jan 17 #Javascript
JS面向对象之单选框实现
Jan 17 #Javascript
原生JavaScript实现的无缝滚动功能详解
Jan 17 #Javascript
You might like
Discuz! Passport 通行证整合
2008/03/27 PHP
PHP原生模板引擎 最简单的模板引擎
2012/04/25 PHP
php页面跳转代码 输入网址跳转到你定义的页面
2013/03/28 PHP
PHP中set error handler函数用法小结
2015/11/11 PHP
php实现微信发红包
2015/12/05 PHP
Centos 6.5系统下编译安装PHP 7.0.13的方法
2016/12/19 PHP
拖动一个HTML元素
2006/12/22 Javascript
『jQuery』名称冲突使用noConflict方法解决
2013/04/22 Javascript
使用GruntJS链接与压缩多个JavaScript文件过程详解
2013/08/02 Javascript
js返回前一页刷新本页重载页面
2014/07/29 Javascript
javascript中if和switch,==和===详解
2015/07/30 Javascript
clipboard.js无需Flash无需依赖任何JS库实现文本复制与剪切
2015/10/10 Javascript
javascript如何创建对象
2016/08/29 Javascript
nodejs微信公众号支付开发
2016/09/19 NodeJs
详解webpack-dev-server使用方法
2018/09/14 Javascript
vue响应式更新机制及不使用框架实现简单的数据双向绑定问题
2019/06/27 Javascript
js中Function引用类型常见有用的方法和属性详解
2019/12/11 Javascript
js实现可爱的气泡特效
2020/09/05 Javascript
利用python微信库itchat实现微信自动回复功能
2017/05/18 Python
python 日期排序的实例代码
2019/07/11 Python
Python SELENIUM上传文件或图片实现过程
2019/10/28 Python
Python安装OpenCV的示例代码
2020/03/05 Python
Python数据正态性检验实现过程
2020/04/18 Python
python mysql自增字段AUTO_INCREMENT值的修改方式
2020/05/18 Python
Python更换pip源方法过程解析
2020/05/19 Python
Fairyseason:为个人和批发商提供女装和配件
2017/03/01 全球购物
尊师重教演讲稿
2014/09/04 职场文书
竞选大队干部演讲稿
2014/09/11 职场文书
大学生第一学年自我鉴定
2014/09/12 职场文书
党员个人承诺书
2015/04/27 职场文书
2015年科学教研组工作总结
2015/07/22 职场文书
演讲稿之开卷有益
2019/08/07 职场文书
爱心捐款倡议书:点燃希望,传递温暖
2019/11/04 职场文书
Java实战之用Swing实现通讯录管理系统
2021/06/13 Java/Android
HTML5+CSS+JavaScript实现捉虫小游戏设计和实现
2021/10/16 HTML / CSS
JavaScript流程控制(分支)
2021/12/06 Javascript