首页 > 其他分享 >vue+axios实现token无感刷新

vue+axios实现token无感刷新

时间:2023-06-21 23:55:24浏览次数:58  
标签:axios return response token Promise error data 无感

原文出处:https://www.jb51.net/javascript/286094r4h.htm

 

通常,对于一些需要记录用户行为的系统,在进行网络请求的时候都会要求传递一下登录的token。不过,为了接口数据的安全,服务器的token一般不会设置太长,根据需要一般是1-7天的样子,token过期后就需要重新登录。不过,频繁的登录会造成体验不好的问题,因此,需要体验好的话,就需要定时去刷新token,并替换之前的token。要做到token的无感刷新,主要有3种方案

方法1.

后端返回过期时间,前端每次请求就判断token的过期时间,如果快到过期时间,就去调用刷新token接口。

缺点:需要后端额外提供一个token过期时间的字段;使用了本地时间判断,若本地时间被篡改,特别是本地时间比服务器时间慢时,拦截会失败。

 

方法2.

写个定时器,然后定时刷新token接口。

缺点:浪费资源,消耗性能,不建议采用。

 

方法3.

在请求响应拦截器中拦截,判断token 返回过期后,调用刷新token接口。综合上面的三个方法,最好的是第三个,因为它不需要占用额外的资源。接下来,我们看一下使用axios进行网络请求,然后响应service.interceptors.response的拦截。

import axios from 'axios'
service.interceptors.response.use(
  response => {
    if (response.data.code === 409) {
        return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => {
          const { token } = res.data
          setToken(token)
          response.headers.Authorization = `${token}`
        }).catch(err => {
          removeToken()
          router.push('/login')
          return Promise.reject(err)
        })
    }
    return response && response.data
  },
  (error) => {
    Message.error(error.response.data.msg)
    return Promise.reject(error)
  }
)

问题一:如何防止多次刷新token

import axios from 'axios'
service.interceptors.response.use(
  response => {
    if (response.data.code === 409) {
      if (!isRefreshing) {
        isRefreshing = true
        return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => {
          const { token } = res.data
          setToken(token)
          response.headers.Authorization = `${token}`
        }).catch(err => {
          removeToken()
          router.push('/login')
          return Promise.reject(err)
        }).finally(() => {
          isRefreshing = false
        })
      }
    }
    return response && response.data
  },
  (error) => {
    Message.error(error.response.data.msg)
    return Promise.reject(error)
  }
)

问题二:同时发起两个或者两个以上的请求时,怎么刷新token

当第二个过期的请求进来,token正在刷新,我们先将这个请求存到一个数组队列中,想办法让这个请求处于等待中,一直等到刷新token后再逐个重试清空请求队列。

那么如何做到让这个请求处于等待中呢?为了解决这个问题,我们得借助Promise。将请求存进队列中后,同时返回一个Promise,让这个Promise一直处于Pending状态(即不调用resolve),此时这个请求就会一直等啊等,只要我们不执行resolve,这个请求就会一直在等待。当刷新请求的接口返回来后,我们再调用resolve,逐个重试。

import axios from 'axios'
// 是否正在刷新的标记
let isRefreshing = false
//重试队列
let requests = []
service.interceptors.response.use(
  response => {
  //约定code 409 token 过期
    if (response.data.code === 409) {
      if (!isRefreshing) {
        isRefreshing = true
        //调用刷新token的接口
        return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => {
          const { token } = res.data
          // 替换token
          setToken(token)
          response.headers.Authorization = `${token}`
           // token 刷新后将数组的方法重新执行
          requests.forEach((cb) => cb(token))
          requests = [] // 重新请求完清空
          return service(response.config)
        }).catch(err => {
        //跳到登录页
          removeToken()
          router.push('/login')
          return Promise.reject(err)
        }).finally(() => {
          isRefreshing = false
        })
      } else {
        // 返回未执行 resolve 的 Promise
        return new Promise(resolve => {
          // 用函数形式将 resolve 存入,等待刷新后再执行
          requests.push(token => {
            response.headers.Authorization = `${token}`
            resolve(service(response.config))
          })
        })
      }
    }
    return response && response.data
  },
  (error) => {
    Message.error(error.response.data.msg)
    return Promise.reject(error)
  }
)

 

标签:axios,return,response,token,Promise,error,data,无感
From: https://www.cnblogs.com/junechen/p/17497331.html

相关文章

  • 登录、token相关,rsa加密
    实例点击查看代码defrsa_encrypt(msg):"""RSA加密:parampub_key_str:公钥:parammsg:待加密信息:return:"""msg=msg.encode('utf-8')length=len(msg)default_length=117#公钥加密publ......
  • node生成token报错:secretOrPrivateKey has a minimum key size of 2048 bits for RS25
    提要:在node生成token时利用用jsonwebtoken,利用非对称加密的生成token  constjwt=require("jsonwebtoken"); constprivateKey=fs.readFileSync("./keys/private.key");constpublicKey=fs.readFileSync("./keys/public.key");consttok......
  • axios
    Axios对原生的AJAX进行封装,简化书写。Axios官网是:​https://www.axios-http.cn​1.基本使用axios使用是比较简单的,分为以下两步:引入axios的js文件<scriptsrc="js/axios-0.18.0.js"></script>使用axios发送请求,并获取响应结果发送get请求axios({  m......
  • 植保机电调无感电机控制器软硬件方案全套,FOC矢量控制 算法,永磁同步电机驱动用,所有源码
    植保机电调无感电机控制器软硬件方案全套,FOC矢量控制算法,永磁同步电机驱动用,所有源码,含观测器部分,全部开源,植保机风机等大功率使用,可直接打板子使用,稳定性非常好,提供硬件原理图,PCB,BOM,软件源代码ID:935000609416290163......
  • 旋转高频电压注入PMSM无感控制MATLAB仿真模型,Mat
    旋转高频电压注入PMSM无感控制MATLAB仿真模型,MatID:2238606091675051......
  • fastadmin 的Http类 请求外部接口携带 Authorization:Bearer token 参数问题
    背景:最近在对接某个系统的支付接口时,接口请求时要求携带token,在请求头header中添加Authorization:Bearer。我使用的框架tp5搭建的fastadmin,里面封装了Http类 出现问题:写法出错,虽然带了参数,但是对方接受不到参数,接口请求验证失败  解决方法:正确的写法代码如下:$info=Ht......
  • 【AGC】云数据库返回403client token authorization fail问题
    【关键字】AGC、云数据库、403【问题描述】有开发者反馈在使用AGC云数据库,拿到access_token用户登录返回403clienttokenauthorizationfail的问题。具体如下所述:用接口:https://connect-drcn.dbankcloud.cn/agc/apigw/oauth2/v1/token拿到了access_token,但用这个token去登录时:htt......
  • Axios封装
    vue-axiosAxios是一个基于promise的HTTP库,可以用在浏览器和node.js中一、流程:1.拿到项目和后端接口,首先要配置全局代理;2.接着全局封装axios和request.js;3.过滤axios请求方式,控制路径,参数的格式,http.js;4.正式封装api.js;5.页面调用;二、具体(1)前......
  • vue中使用axios
    引入axios错误用法在main.js中引入,需要注意的是,因为axios是第三方库,不是vue的插件,所以下面的这种写法不支持。importaxiosfrom'axios';Vue.use(axios)正确用法结合vue-axios使用,vue-axios是将axios集成到Vue.js的小包装器,可以像插件一样进行安装,具体用法是:安装......
  • axios的挂载
    axios的挂载请求示例如下,每一次都要导入axios,每一个组件都相当于vue的实例。 <template> <divclass="left-container">  <h3>left</h3>  <button@click="getInfo">GET</button> </div></template>​<script>import......