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 相关文章推荐
关于viewport,Ext.panel和Ext.form.panel的关系
May 07 Javascript
JQuery与iframe交互实现代码
Dec 24 Javascript
jQuery 瀑布流 浮动布局(一)(延迟AJAX加载图片)
May 23 Javascript
javascript 树形导航菜单实例代码
Aug 13 Javascript
JavaScript数据类型学习笔记分享
Sep 01 Javascript
javascript 闭包详解及简单实例应用
Dec 31 Javascript
vuex的使用及持久化state的方式详解
Jan 23 Javascript
vue实现底部菜单功能
Jul 24 Javascript
利用angular自动编译andriod APK的绕坑经历分享
Mar 08 Javascript
了解JavaScript函数中的默认参数
May 30 Javascript
python实现迭代法求方程组的根过程解析
Nov 25 Javascript
vue.config.js中配置Vue的路径别名的方法
Feb 11 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和javascript之间变量的传递实现代码
2012/12/19 PHP
5种PHP创建数组的实例代码分享
2014/01/17 PHP
php获取CSS文件中图片地址并下载到本地的方法
2014/12/02 PHP
php中get_meta_tags()、CURL与user-agent用法分析
2014/12/16 PHP
php检查字符串中是否包含7位GSM字符的方法
2015/03/17 PHP
Win7下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
用Jquery选择器计算table中的某一列某一行的合计
2014/08/13 Javascript
Nodejs极简入门教程(一):模块机制
2014/10/25 NodeJs
js仿百度登录页实现拖动窗口效果
2016/03/11 Javascript
jQuery on()方法绑定动态元素的点击事件无响应的解决办法
2016/07/07 Javascript
BootStrap学习笔记之nav导航栏和面包屑导航
2017/01/03 Javascript
xmlplus组件设计系列之图标(ICON)(1)
2017/05/05 Javascript
jQuery中的deferred对象和extend方法详解
2017/05/08 jQuery
Javascript实现倒计时时差效果
2017/05/18 Javascript
详解如何在angular2中获取节点
2017/11/23 Javascript
js实现简单选项卡功能
2020/03/23 Javascript
微信小程序云开发之使用云数据库
2019/05/17 Javascript
微信小程序自定义组件实现环形进度条
2020/11/17 Javascript
layui 上传图片 返回图片地址的方法
2019/09/26 Javascript
浅谈vue3中effect与computed的亲密关系
2019/10/10 Javascript
Python内置的HTTP协议服务器SimpleHTTPServer使用指南
2016/03/30 Python
python中关于for循环的碎碎念
2017/06/30 Python
python中协程实现TCP连接的实例分析
2018/10/14 Python
python函数定义和调用过程详解
2020/02/09 Python
Python使用socket模块实现简单tcp通信
2020/08/18 Python
英国排名第一的在线宠物用品商店:Monster Pet Supplies
2018/05/20 全球购物
Hammitt官网:设计师手袋
2020/05/23 全球购物
高中生自我评价个人范文
2013/11/09 职场文书
公证委托书大全
2014/04/04 职场文书
组工干部演讲稿
2014/09/02 职场文书
夫妻双方自愿离婚协议书怎么写
2014/12/01 职场文书
责任书范本大全
2015/05/11 职场文书
日本读研:怎样写好一篇日本研究计划书?
2019/07/15 职场文书
Django中的JWT身份验证的实现
2021/05/07 Python
IDEA 链接Mysql数据库并执行查询操作的完整代码
2021/05/20 MySQL
python 判断文件或文件夹是否存在
2022/03/18 Python