vue下axios拦截器token刷新机制

//创建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);
        });

这是本人做自动刷新token遇到的问题,现在分享给大家,如果对你有帮助记得留言,谢谢!!

原文地址:https://www.cnblogs.com/cxf1992/p/12205074.html

时间: 2024-10-31 12:31:22

vue下axios拦截器token刷新机制的相关文章

vue导航守卫和axios拦截器的区别

在Vue项目中,有两种用户登录状态判断并处理的情况,分别为:导航守卫和axios拦截器. 一.什么是导航守卫? vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航.(在路由跳转时触发) 我们主要介绍的是可以验证用户登录状态的全局前置守卫,当一个导航触发时,全局前置守卫按照创建顺序调用.守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中. const router = new VueRouter({ ... }) router.beforeEach(

Vue2学习小记-给Vue2路由导航钩子和axios拦截器做个封装

1.写在前面 最近在学习Vue2,遇到有些页面请求数据需要用户登录权限.服务器响应不符预期的问题,但是总不能每个页面都做单独处理吧,于是想到axios提供了拦截器这个好东西,再于是就出现了本文. 2.具体需求 用户鉴权与重定向:使用Vue提供的路由导航钩子 请求数据序列化:使用axios提供的请求拦截器 接口报错信息处理:使用axios提供的响应拦截器 3.简单实现 3.1 路由导航钩子层面鉴权与重定向的封装 路由导航钩子所有配置均在router/index.js,这里是部分代码 import

Axios拦截器配置

Axios 拦截器的配置如下 分三块:基础配置.请求之前拦截.响应之前拦截 发送所有请求之前和操作服务器响应数据之前对这种情况过滤. http request 请求拦截器 每次发送请求之前判断是否存在 此时要是验证符合条件则通过,否则不符合的不给通过 具体代码如下: html文件 option2.php文件 因为博客园不支持上传js文件 只能截图了 至此,就可以看到结果了,就可以看到控制台的打印信息 原文地址:https://www.cnblogs.com/ddlove/p/9957087.ht

drf框架 8 系统权限类使用 用户中心信息自查 token刷新机制 认证组件项目使用:多方式登录 权限组件项目使用:vip用户权限 频率组件 异常组件项目使用

系统权限类使用 图书接口:游客只读,用户可增删改查权限使用 from rest_framework.permissions import IsAuthenticatedOrReadOnly class BookViewSet(ModelViewSet): # 游客只读,用户可增删改查 permission_classes = [IsAuthenticatedOrReadOnly] queryset = models.Book.objects.all() serializer_class = se

vue axios 拦截器

前言 项目中需要验证登录用户身份是否过期,是否有权限进行操作,所以需要根据后台返回不同的状态码进行判断. 第一次使用拦截器,文章中如有不对的地方还请各位大佬帮忙指正谢谢. 正文 axios的拦截器分为请求拦截器和响应拦截器两种.我一般把拦截器写在main.js里. mian.js//axios请求 import Axios from "axios"; Vue.prototype.$axios = Axios; 请求拦截器 axios.interceptors.request.use(

Vue添加请求拦截器

一.现象 统一处理错误及配置请求信息 二.解决 1.安装 axios  , 命令: npm install axios --save-dev 2.在根目录的config目录下新建文件 axios.js  ,内容如下: import axios from 'axios' // 配置默认的host,假如你的API host是:http://api.htmlx.clubaxios.defaults.baseURL = 'http://api.htmlx.club' // 添加请求拦截器axios.in

vue配置请求拦截器和响应拦截器

首先确保我们已经设置的store.js进行值的存取,这时候我们需要配置请求和响应的拦截器设置 main.js import Vue from 'vue' import App from './App' import router from './router' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import axios from 'axios' // 引入store i

springmvc 用拦截器+token防止重复提交

一,原理: 1,在进入到提交页面时,使用拦截器拦截在进入此方法前,生成一个token,放到session中, @RequestMapping(value = "/{id}/details") @FormToken(produce = true) public Object details(@PathVariable String id, HttpServletRequest request){ Map<String,Object> map = new HashMap<

axios拦截器+mockjs

//main.js中 //引入你mock.js文件 require('./mock.js') //封装api请求 //src/axios/api.js import axios from 'axios' import vue from 'vue' axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded' // 请求拦截器 axios.interceptors.request.use(func