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 相关文章推荐
JQuery的ready函数与JS的onload的区别详解
Nov 21 Javascript
js跳转页面方法总结
Jan 29 Javascript
javascript判断office版本示例
Apr 11 Javascript
简介JavaScript中strike()方法的使用
Jun 08 Javascript
jquery操作angularjs对象
Jun 26 Javascript
jQuery实现返回顶部功能
Feb 23 Javascript
jQuery取消特定的click事件
Feb 29 Javascript
jQuery弹出遮罩层效果完整示例
Sep 13 Javascript
详细分析jsonp的原理和实现方式
Nov 20 Javascript
vue-swiper的使用教程
Aug 30 Javascript
Node.js开发之套接字(socket)编程入门示例
Nov 05 Javascript
解决vue-cli@3.xx安装不成功的问题及搭建ts-vue项目
Feb 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
在VS2008中编译MYSQL5.1.48的方法
2010/07/03 PHP
php基于base64解码图片与加密图片还原实例
2014/11/03 PHP
php+ajax实现仿百度查询下拉内容功能示例
2017/10/20 PHP
浅谈laravel中的关联查询with的问题
2019/10/10 PHP
跨浏览器开发经验总结(三)   警惕“IE依赖综合症”
2010/05/13 Javascript
异步javascript的原理和实现技巧介绍
2012/11/08 Javascript
ajax处理php返回json数据的实例代码
2013/01/24 Javascript
用js实现table单元格高宽调整,兼容合并单元格(兼容IE6、7、8、FF)实例
2013/06/25 Javascript
Extjs表单常见验证小结
2014/03/07 Javascript
js实现网页随机切换背景图片的方法
2014/11/01 Javascript
AngularJS入门教程之Hello World!
2014/12/06 Javascript
NodeJS Web应用监听sock文件实例
2015/02/18 NodeJs
jQuery+css实现的蓝色水平二级导航菜单效果代码
2015/09/11 Javascript
JavaScript中的splice方法用法详解
2016/07/20 Javascript
微信小程序 网络请求(post请求,get请求)
2017/01/17 Javascript
详解Vue This$Store总结
2018/12/17 Javascript
iview的table组件自带的过滤器实现
2019/07/12 Javascript
JavaScript对象原型链原理详解
2020/02/05 Javascript
解决vue项目运行npm run serve报错的问题
2020/10/26 Javascript
[12:21]VICI vs TNC (BO3)
2018/06/07 DOTA
python中PIL安装简单教程
2016/04/21 Python
windows下ipython的安装与使用详解
2016/10/20 Python
Python 安装第三方库 pip install 安装慢安装不上的解决办法
2019/06/18 Python
Python3 批量扫描端口的例子
2019/07/25 Python
Python学习笔记之lambda表达式用法详解
2019/08/08 Python
python中单下划线(_)和双下划线(__)的特殊用法
2019/08/29 Python
解决导入django_filters不成功问题No module named 'django_filter'
2020/07/15 Python
Python在字符串中处理html和xml的方法
2020/07/31 Python
Python中正则表达式对单个字符,多个字符和匹配边界等使用
2021/01/27 Python
html5 实现客户端验证上传文件的大小(简单实例)
2016/05/15 HTML / CSS
瑞典轮胎在线:Tirendo.se
2018/06/21 全球购物
Java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类
2012/02/06 面试题
充分就业社区汇报材料
2014/05/07 职场文书
2014年人事科工作总结
2014/11/19 职场文书
维稳承诺书
2015/01/20 职场文书
2019年警察入党转正申请书最新范文
2019/09/03 职场文书