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 相关文章推荐
Document对象内容集合(比较全)
Sep 06 Javascript
js数值计算时使用parseInt进行数据类型转换(jquery)
Oct 07 Javascript
js实现不提交表单获取单选按钮值的方法
Aug 21 Javascript
轻松实现javascript数据双向绑定
Nov 11 Javascript
JavaScript中setter和getter方法介绍
Jul 11 Javascript
js轮播图代码分享
Jul 14 Javascript
codeMirror插件使用讲解
Jan 16 Javascript
浅析vue component 组件使用
Mar 06 Javascript
ES6新特性七:数组的扩充详解
Apr 21 Javascript
JScript实现地址选择功能
Aug 15 Javascript
JS多个异步请求 按顺序执行next实现解析
Sep 16 Javascript
jQuery+ajax实现文件上传功能
Dec 22 jQuery
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
如何设置mysql允许外网访问
2013/06/04 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
PHP+mysql实现从数据库获取下拉树功能示例
2017/01/06 PHP
PHP聊天室简单实现方法详解
2018/12/08 PHP
不安全的常用的js写法
2009/09/15 Javascript
JQuery调用WebServices的方法和4个实例
2014/05/06 Javascript
jquery+css3实现网页背景花瓣随机飘落特效
2015/08/17 Javascript
js Canvas绘制圆形时钟教程
2017/02/06 Javascript
jQuery插件FusionCharts绘制2D柱状图和折线图的组合图效果示例【附demo源码】
2017/04/10 jQuery
浅谈Vue-cli 命令行工具分析
2017/11/22 Javascript
基于vue.js中事件修饰符.self的用法(详解)
2018/02/23 Javascript
微信小程序上传图片功能(附后端代码)
2020/06/19 Javascript
js实现图片上传并预览功能
2018/08/06 Javascript
vue-router权限控制(简单方式)
2018/10/29 Javascript
微信上传视频文件提示(推荐)
2018/11/22 Javascript
Bootstarp在pycharm中的安装及简单的使用方法
2019/04/19 Javascript
详解小程序开发经验:多页面数据同步
2019/05/18 Javascript
在微信小程序中使用mqtt服务的方法
2019/12/13 Javascript
python获取图片颜色信息的方法
2015/03/18 Python
Python使用MYSQLDB实现从数据库中导出XML文件的方法
2015/05/11 Python
python 递归遍历文件夹,并打印满足条件的文件路径实例
2017/08/30 Python
对python中的for循环和range内置函数详解
2018/04/17 Python
Python+OpenCV实现图像融合的原理及代码
2018/12/03 Python
正则给header的冒号两边参数添加单引号(Python请求用)
2019/08/09 Python
pandas按行按列遍历Dataframe的几种方式
2019/10/23 Python
如何解决cmd运行python提示不是内部命令
2020/07/01 Python
C#如何调用Word并打开一个Word文档
2013/05/08 面试题
什么是makefile? 如何编写makefile?
2013/01/02 面试题
内科护士实习自我鉴定
2013/10/17 职场文书
质量工程师岗位职责
2013/11/16 职场文书
品质主管的岗位职责
2013/12/04 职场文书
竞选团支书演讲稿
2014/04/28 职场文书
国际贸易毕业生自荐书
2014/06/22 职场文书
刑事附带民事上诉状
2015/05/23 职场文书
飞屋环游记观后感
2015/06/08 职场文书
2016父亲节感恩话语
2015/12/09 职场文书