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 相关文章推荐
用脚本调用样式的几种方法
Dec 09 Javascript
JavaScript将XML转成JSON的方法
Mar 12 Javascript
node.js读取文件到字符串的方法
Jun 29 Javascript
javascript图片预加载实例分析
Jul 16 Javascript
js实现网页抽奖实例
Aug 05 Javascript
jquery实现横向图片轮播特效代码分享
Nov 19 Javascript
老生常谈jquery id选择器和class选择器的区别
Feb 12 Javascript
Vue.directive()的用法和实例详解
Mar 04 Javascript
详解Vue路由自动注入实践
Apr 17 Javascript
layui禁用侧边导航栏点击事件的解决方法
Sep 25 Javascript
详解ES6中class的实现原理
Oct 03 Javascript
夯基础之手撕javascript继承详解
Nov 09 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
利用PHP创建动态图像
2006/10/09 PHP
解析PayPal支付接口的PHP开发方式
2010/11/28 PHP
PHP数组及条件,循环语句学习
2012/11/11 PHP
深入PHP许愿墙模块功能分析
2013/06/25 PHP
php自定义函数截取汉字长度
2014/05/15 PHP
php Imagick获取图片RGB颜色值
2014/07/28 PHP
使用XHGui来测试PHP性能的教程
2015/07/03 PHP
javascript Keycode对照表
2009/10/24 Javascript
文档对象模型DOM通俗讲解
2013/11/01 Javascript
Javascript 实现微信分享(QQ、朋友圈、分享给朋友)
2016/10/21 Javascript
开源免费天气预报接口API及全国所有地区代码(国家气象局提供)
2016/12/26 Javascript
Vue computed计算属性的使用方法
2017/07/14 Javascript
深入理解vue Render函数
2017/07/19 Javascript
微信小程序“摇一摇”的实例代码
2017/07/20 Javascript
webpack中的热刷新与热加载的区别
2018/04/09 Javascript
vue.js中proxyTable 转发请求的实现方法
2018/09/20 Javascript
详解js实时获取并显示当前时间的方法
2019/05/10 Javascript
vue.js实现备忘录demo
2019/06/26 Javascript
详解vuex数据传输的两种方式及this.$store undefined的解决办法
2019/08/26 Javascript
对layui中table组件工具栏的使用详解
2019/09/19 Javascript
JS实现音乐导航特效
2020/01/06 Javascript
[10:34]DOTA2上海特级锦标赛全纪录
2016/03/25 DOTA
[49:59]KG vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
python根据出生年份简单计算生肖的方法
2015/03/27 Python
插入排序_Python与PHP的实现版(推荐)
2017/05/11 Python
简单易懂的python环境安装教程
2017/07/13 Python
PyQt5利用QPainter绘制各种图形的实例
2017/10/19 Python
Python面向对象程序设计类变量与成员变量、类方法与成员方法用法分析
2019/04/12 Python
对django 2.x版本中models.ForeignKey()外键说明介绍
2020/03/30 Python
使用HTML5的Notification API制作web通知的教程
2015/05/08 HTML / CSS
美国摄影爱好者购物网站:Focus Camera
2016/10/21 全球购物
美国名牌太阳镜折扣网站:Eyedictive
2017/05/15 全球购物
英国护发和美妆在线商店:Klip Shop
2019/03/24 全球购物
AJAX的全称是什么
2012/11/06 面试题
大学军训自我鉴定大全
2014/09/18 职场文书
Go语言安装并操作redis的go-redis库
2022/04/14 Golang