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 将disabled的元素置为enabled的三种方法
Jul 25 Javascript
ASP.NET jQuery 实例5 (显示CheckBoxList成员选中的内容)
Jan 13 Javascript
JQuery的Ajax跨域请求原理概述及实例
Apr 26 Javascript
深入理解JavaScript是如何实现继承的
Dec 12 Javascript
在AngularJS框架中处理数据建模的方式解析
Mar 05 Javascript
JS实现数字格式千分位相互转换方法
Aug 01 Javascript
javascript实现鼠标点击页面 移动DIV
Dec 02 Javascript
学习Vue组件实例
Apr 28 Javascript
微信小程序自定义底部弹出框
Nov 16 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
Jan 30 Javascript
微信小程序自定义弹窗实现详解(可通用)
Jul 04 Javascript
Preload基础使用方法详解
Feb 03 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 5.0对象模型深度探索之类的静态成员
2008/03/27 PHP
PHP函数学习之PHP函数点评
2012/07/05 PHP
php基于session实现数据库交互的类实例
2015/08/03 PHP
php快速导入大量数据的实例方法
2019/09/23 PHP
添加JavaScript重载函数的辅助方法2
2010/07/04 Javascript
JavaScript实现点击按钮字体放大、缩小
2016/02/29 Javascript
jQuery简单实现仿京东分类导航层效果
2016/06/07 Javascript
JavaScript蒙板(model)功能的简单实现代码
2016/08/04 Javascript
微信小程序 引用其他js文件实现代码
2017/02/22 Javascript
老生常谈angularjs中的$state.go
2017/04/24 Javascript
微信小程序实现漂亮的弹窗效果
2020/05/26 Javascript
JS+CSS+HTML实现“代码雨”类似黑客帝国文字下落效果
2020/03/17 Javascript
Python实现周期性抓取网页内容的方法
2015/11/04 Python
使用简单工厂模式来进行Python的设计模式编程
2016/03/01 Python
python之Character string(实例讲解)
2017/09/25 Python
Python爬虫基础之XPath语法与lxml库的用法详解
2018/09/13 Python
numpy 对矩阵中Nan的处理:采用平均值的方法
2018/10/30 Python
ActiveMQ:使用Python访问ActiveMQ的方法
2019/01/30 Python
详解Python_shutil模块
2019/03/15 Python
python中的Elasticsearch操作汇总
2019/10/30 Python
Python 函数绘图及函数图像微分与积分
2019/11/20 Python
pycharm 中mark directory as exclude的用法详解
2020/02/14 Python
python利用Excel读取和存储测试数据完成接口自动化教程
2020/04/30 Python
如何利用python web框架做文件流下载的实现示例
2020/06/02 Python
Joseph官网:英国小众奢侈品牌
2019/05/17 全球购物
社区工作者思想汇报
2014/01/13 职场文书
社团文化节策划书
2014/02/01 职场文书
竞聘演讲稿精彩开头和结尾
2014/05/14 职场文书
婚纱店策划方案
2014/05/22 职场文书
人力资源管理专业自荐书
2014/07/07 职场文书
学生意外伤害赔偿协议书
2014/09/17 职场文书
教师党员先进性教育自我剖析材料思想汇报
2014/09/24 职场文书
英语导游欢迎词
2015/09/30 职场文书
HTML基础-标签分类(闭合标签,空标签,块级元素,行内元素,行级块元素,可替换元素)
2021/03/31 HTML / CSS
python Tkinter模块使用方法详解
2022/04/07 Python
阿里云服务器(windows)手动部署FTP站点详细教程
2022/08/05 Servers