前端实现token的无感刷新--VUE

token刷新的方案
   方案一:后端返回过期时间,前端判断token过期时间,去调用刷新token的接口
   缺点:需要后端提供一个token过期时间的字段;使用本地时间判断,若本地时间被修改,本地时间比服务器时间慢,拦截会失败。

   方案二:写个定时器,定时刷新token接口
   缺点:浪费资源,消耗性能,不建议采用

   方案三:在响应拦截器中拦截,判断token返回过期后,调用刷新token接口(⭕推荐使用)

token失效后接口返回401 

有感刷新: 清除token,强制跳转回登录页,有感知的重新登录拿到新token替换到本地,体验不好 !

if (res.code == '401' || res.code =="493"){EIMessage.warning("登录已失效,请重新登录 !)sessionstorage.clear()localstorage .removeitem('token')router.push({ path:  /login' })return
}

无感刷新: 使用登录时保存的refresh_token调用另一个接口,换回新的token值,替换到本地,再次完成本次未完成的请求(用户无感知)
具体步骤:
1、首次登录的时候会获取到两个token, 一个是平时请求接口正常使用的token(过期时间短),另一个是专门用于刷新的refresh_token(过期时间一般比较长),登陆时都存起来 localStorage.setItem(‘refresh_token’,xxx) localStorage.setItem(‘token’, xxx)
2、在响应拦截器中对401状态码引入刷新token的api方法调用
3、替换保存本地新的token
4、headers替换新的token
5、axios再次发起未完成的请求,返回promise对象到最开始发起请求的页面
6、如果refresh_token也过期了,那就判断是否过期,过期了就清除localstorage跳转回登录页面
 

登陆时拿到的后端数据:

存起来

refreshToken.js

import request from './requestexport function refreshToken() {const resp = request.get('/refresh_token', {headers: {token: `${refresh_token}`},__isRefreshToken: true})// return resp.code === 0 // 等于0表示刷新token成功
}export function isRefreshRequest(config) {return !!config.__isRefreshToken //两个取反,变成boolean
}

request.js

import axios from 'axios'
import { refreshToken, isRefreshRequest } form './refreshToken.js'// 创建axios实例
const service = axios.create({// baseURL: '',// 所有的请求地址前缀部分timeout: 25000, // 请求超时时间(毫秒)withCredentials: true// 异步请求携带cookie
})// 请求拦截器
service.interceptors.request.use((config: any) => {...
}, error => {...
})// 响应拦截器
service.interceptors.response.use((response: any) => {let res = response.dataif (res.code == '401' && !isRefreshRequest(res.config)){ // 如果没有权限且不是刷新token的请求// 刷新tokentry {const res = await refreshToken()// 保存新的tokenlocalStorage.setItem('token', res.data.token)// 有新token后再重新请求response.config.headers.token = localStorage.getItem('token') // 新tokenconst resp = await service.request(response.config)return resp.data// return service(response.config)}catch {localStorage.clear() // 清除tokenrouter.replace('/login') // 跳转到登录页}}
}, error => {...console.log('error', error)return Promise.reject(error)
})

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

为了防止多次刷新token,可以通过一个变量isRefreshing 去控制是否在刷新token的状态

request.js

import axios from 'axios'
import { refreshToken, isRefreshRequest } form './refreshToken.js'// 创建axios实例
const service = axios.create({// baseURL: '',// 所有的请求地址前缀部分timeout: 25000, // 请求超时时间(毫秒)withCredentials: true// 异步请求携带cookie
})// 请求拦截器
service.interceptors.request.use((config: any) => {...
}, error => {...
})// 响应拦截器
service.interceptors.response.use((response: any) => {let res = response.datalet isRefreshing = falseif (res.code == '401' && ! isRefreshRequest(res.config)){ // 如果没有权限且不是刷新token的请求if (!isRefreshing) {isRefreshing = true// 刷新tokentry {const res = await refreshToken()// 保存新的tokenlocalStorage.setItem('token', res.data.token)// 有新token后再重新请求response.config.headers.token = localStorage.getItem('token') // 新tokenconst resp = await service.request(response.config)return resp.data// return service(response.config)}catch {localStorage.clear() // 清除tokenrouter.replace('/login') // 跳转到登录页}isRefreshing = false}}
}, error => {...console.log('error', error)return Promise.reject(error)
})

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

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

request.js

import axios from 'axios'
import { refreshToken, isRefreshRequest } form './refreshToken.js'// 创建axios实例
const service = axios.create({// baseURL: '',// 所有的请求地址前缀部分timeout: 25000, // 请求超时时间(毫秒)withCredentials: true// 异步请求携带cookie
})// 请求拦截器
service.interceptors.request.use((config: any) => {...
}, error => {...
})// 响应拦截器
service.interceptors.response.use((response: any) => {let res = response.datalet isRefreshing = falselet requests = [] // 请求队列if (res.code == '401' && isRefreshRequest(res.config)){ // 如果没有权限且不是刷新token的请求if (!isRefreshing) {isRefreshing = true// 刷新tokentry {const res = await refreshToken()// 保存新的tokenlocalStorage.setItem('token', res.data.token)// 有新token后再重新请求response.config.headers.token = localStorage.getItem('token') // 新token// token 刷新后将数组的方法重新执行requests.forEach((cb) => cb(token))requests = [] // 重新请求完清空const resp = await service.request(response.config)return resp.data// return service(response.config)}catch {localStorage.clear() // 清除tokenrouter.replace('/login') // 跳转到登录页}isRefreshing = false} else {// 返回未执行 resolve 的 Promisereturn new Promise(resolve => {// 用函数形式将 resolve 存入,等待刷新后再执行request.push(token => {response.config.headers.token = `${token}`resolve(service(response.config))})})}}
}, error => {...console.log('error', error)return Promise.reject(error)
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【解决】Unity 工程无法正常打开而崩溃问题

开发平台:Unity 2022.3.17f1c1 一、问题描述 访问 Unity 工程等待 Open Projet(busy for 时间),出现崩溃、闪退等情况,导致无法正常进入Unity编辑页面。 二、问题分析 笔者在 URP 渲染管线下处理 Obi Fluid 流体插件 D…

Docker本地部署Firefox浏览器并结合内网穿透公网访问

文章目录 1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox Firefox是一款免费开源的网页浏览器,由Mozilla基金会开发和维护。它是第一个成功挑战微软Internet Explorer浏…

尝试搭建域

使用window 7 作为dmz 主机 server_2008 作为 预控 前提两台主机都在同一个LAN 下(设置一个LAN 区域),同样防火墙关闭状态 首先搞定server 2008 中的域 1. 在计算机属性中选择更改设置中将主机名修改一下: 2. 在server 2008 中…

echarts 柱状图数据过多时自动滚动

当我们柱状图中X轴数据太多的时候,会自动把柱形的宽度挤的很细,带来的交互非常不好,我们可以用dataZoom属性来解决 简易的版本,横向滚动。 option.dataZoom [{type: "slider",show: true,startValue: 0, //数据窗口范…

【刷题】牛客网 NC132 环形链表的约瑟夫问题

NC132 环形链表的约瑟夫问题 题目描述思路一(链表直通版)思路二(数组巧解版)思路三(变态秒杀版)Thanks♪(・ω・)ノ谢谢阅读下一篇文章见!!&#xff…

Oracle 的闪回技术是什么

什么是闪回 Oracle 数据库闪回技术是一组独特而丰富的数据恢复解决方案,能够有选择性地高效撤销一个错误的影响,从人为错误中恢复。闪回是一种数据恢复技术,它使得数据库可以回到过去的某个状态,可以满足用户的逻辑错误的快速恢复…

SpringCloudAlibaba组件总结笔记(如Nacos、SpringCloudGateway、OpenFeign,Ribbon,RabbitMQ)

这目录 1.Ribbon负载均衡1负载均衡原理2.负载均衡策略1.负载均衡策略2.自定义负载均衡策略 3.饥饿加载 2.Nacos注册中心与Eureka的区别3.Nacos配置中心1.从微服务拉取配置2.配置热更新1.2.1.方式一1.2.2.方式二 3.配置共享1.配置共享的优先级 4.Feign1.Feign使用优化2.配置连接…

使用Promethues+Grafana监控Elasticsearch

PromethuesGrafana监控Elasticsearch 监控选用说明指标上报流程说明实现监控的步骤搭建elasticsearch-exporter服务搭建promethues和grafana服务 监控选用说明 虽然用Kibana来监控ES,能展示一些关键指标,但ES本身收集的指标并不全面,还需要在…

torchvision.models._utils.IntermediateLayerGetter()使用

torchvision.models._utils.IntermediateLayerGetter()使用 源码如下: from collections import OrderedDictimport torch from torch import nnclass IntermediateLayerGetter(nn.ModuleDict):"""Module wrapper that ret…

Python采集学习笔记-读取excel数据

表格格式 方法一:使用xlrd import xlrd 1.读取Excel文件 workbook xlrd.open_workbook(plc.xlsx) 2.读取第一个表 sheet workbook.sheet_by_index(0) 3.获取表格总行数 total_rows sheet.nrows 4.创建列表,存储表格一行中每一列信息 plc_info [] for row in range(1…

【JAVA】Long类型返回到前端,精度丢失

一. 问题阐述 20位long类型的数字,从后端接口返回到前端后【四舍五入】 MYSQL端 (1)bigint (20) (2)具体某一条数据 JAVA端 (1)实体类 (2)服务类 (3&…

docker可视化操作

docker可视化操作,ui界面操作 1.检查docker服务状态 docker status2.安装服务 部署 Portainer 1.从镜像仓库中拉取 Portainer:docker pull portainer/portainer2.创建数据卷: docker volume create portainer_db 3.启动 Portainer命令&…

86.网游逆向分析与插件开发-物品使用-物品丢弃的逆向分析与C++代码的封装

内容参考于:易道云信息技术研究院VIP课 上一个内容:物品使用的逆向分析与C代码的封装-CSDN博客 码云地址(ui显示角色数据 分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:7563f86877c…

NFTScan 与 Merlin Protocol 共同推出 BRC20 Indexer Oracle,于今日正式上线!

近日,NFT 数据基础设施 NFTScan 与 Merlin Protocol 进行战略合作,联合推出了比特币网络原生资产 Indexer Oracle 服务,现在该服务已在 NFTScan 开发者平台上线,任何开发者都可以注册使用! Merlin Protocol 是一个专用…

linux 磁盘标签类型MBR转换为GPT

[rootlocalhost /]# fdisk -l 磁盘 /dev/sda:299.4 GB, 299439751168 字节,584843264 个扇区 Units 扇区 of 1 * 512 512 bytes 扇区大小(逻辑/物理):512 字节 / 512 字节 I/O 大小(最小/最佳):512 字节 / 512 字节 磁盘标签类…

解读 HTTP 和 HTTPS:有何异同?

超文本传输安全协议(HTTPS)是建立在超文本传输协议(HTTP)之上的一种安全网络传输协议。在计算机网络上传输时,HTTPS 通过传输层安全性(TLS)或它的前身安全套接字层(SSL)为…

谷歌上架防关联VPS开到和原来一样的IP造成关联?应该怎么选?

随着Google paly的发展,竞争越来越激烈,开发者们也面临的越来越多的挑战。其中,如何降低关联风险是开发者们重点关注的问题。 为了防止开发者账号的滥用或欺诈,谷歌会通过判断账号之间是否存在关联,并对违规账号进行处…

【Vue】二、Vue 组件展示控制的优雅解决方案

vue项目中展示的组件,我平常都是通过v-show进行展示控制,类似这样 通常情况下,一个正常展示组件的流程,是通过前端用户点击触发函数,在函数中对data数据进行操作,从而展示不同的页面 showWork: false, sho…

首次接触共享办公室,有哪些问题需要注意?

随着互联网和创业的发展,越来越多的企业和个人选择共享办公空间作为他们的办公场所。共享办公空间是一种提供灵活的办公模式和配套的设施和服务的空间,可以帮助企业和个人节省成本和空间,提高效率和创新,拓展人脉和资源。但是&…

【C++】STL之空间配置器(了解)

一、什么是空间配置器 空间配置器 ,顾名思义就是为各个容器高效的管理空间(空间的申请与回收)的,在默默地工作。虽然在常规使用 STL 时,可能用不到它,但站在学习研究的角度,学习它的实现原理对…