首页IT科技前端无感刷新token(记录–关于无感刷新Token,我是这样子做的)

前端无感刷新token(记录–关于无感刷新Token,我是这样子做的)

时间2025-06-18 12:01:55分类IT科技浏览5789
导读:这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 标头 header...

这里给大家分享我在网上总结出来的一些知识             ,希望对大家有所帮助

标头 header

标头是一个JSON对象                        ,由两个部分组成       ,分别是令牌是类型(JWT)和签名算法(SHA256         ,RSA)

{ "alg": "HS256", "typ": "JWT" }
负荷 payload

负荷部分也是一个JSON对象                       ,用于存放需要传递的数据           ,例如用户的信息

{ "username": "_island", "age": 18 }

此外      ,JWT规定了7个可选官方字段(建议)

属性 说明 iss JWT签发人 exp JWT过期时间 sub JWT面向用户 aud JWT接收方 nbf JWT生效时间 iat JWT签发时间 jti JWT编号

签章 signature

这一部分                      ,是由前面两个部分的签名               ,防止数据被篡改                。 在服务器中指定一个密钥   ,使用标头中指定的签名算法                     ,按照下面的公式生成这签名数据

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

在拿到签名数据之后                   ,把这三个部分的数据拼接起来,每个部分中间使用.来分隔                    。这样子我们就生成出一个了JWT数据了                 ,接下来返回给客户端储存起来        。而且客户端在发起请求时                       ,携带这个JWT在请求头中的Authorization字段   ,服务器通过解密的方式即可识别出对应的用户信息            。

JWT优势和弊端

优势 数据体积小             ,传输速度快 无需额外资源开销来存放数据 支持跨域验证使用 弊端 生成出来的Token无法撤销                        ,即使重置账号密码之前的Token也是可以使用的(需等待JWT过期) 无法确认用户已经签发了多少个JWT 不支持refreshToken

关于refreshToken

refreshToken是Oauth2认证中的一个概念       ,和accessToken一起生成出来的                    。

当用户携带的这个accessToken过期时         ,用户就需要在重新获取新的accessToken                       ,而refreshToken就用来重新获取新的accessToken的凭证           。

为什么要有refreshToken

当你第一次接触的时候           ,你有没有一个这样子的疑惑      ,为什么需要refreshToken这个东西                      ,而不是服务器端给一个期限较长甚至永久性的accessToken呢?

抱着这个疑惑我在网上搜寻了一番               ,

其实这个accessToken的使用期限有点像我们生活中的入住酒店   ,当我们在入住酒店时                     ,会出示我们的身份证明来登记获取房卡                   ,此时房卡相当于accessToken,可以访问对应的房间                 ,当你的房卡过期之后就无法再开启房门了                       ,此时就需要再到前台更新一下房卡   ,才能正常进入             ,这个过程也就相当于refreshToken        。

accessToken使用率相比refreshToken频繁很多                        ,如果按上面所说如果accessToken给定一个较长的有效时间       ,就会出现不可控的权限泄露风险                     。

使用refreshToken可以提高安全性

用户在访问网站时         ,accessToken被盗取了                       ,此时攻击者就可以拿这个accessToke访问权限以内的功能了              。如果accessToken设置一个短暂的有效期2小时           ,攻击者能使用被盗取的accessToken的时间最多也就2个小时      ,除非再通过refreshToken刷新accessToken才能正常访问    。

设置accessToken有效期是永久的                      ,用户在更改密码之后               ,之前的accessToken也是有效的

总体来说有了refreshToken可以降低accessToken被盗的风险

关于JWT无感刷新TOKEN方案(结合axios)

业务需求

在用户登录应用后   ,服务器会返回一组数据                     ,其中就包含了accessToken和refreshToken                   ,每个accessToken都有一个固定的有效期,如果携带一个过期的token向服务器请求时                 ,服务器会返回401的状态码来告诉用户此token过期了                       ,此时就需要用到登录时返回的refreshToken调用刷新Token的接口(Refresh)来更新下新的token再发送请求即可                      。

话不多说   ,先上代码

工具

axios作为最热门的http请求库之一             ,我们本篇文章就借助它的错误响应拦截器来实现token无感刷新功能                 。

具体实现

本次基于axios-bz代码片段封装响应拦截器 可直接配置到你的项目中使用 ✈️ ✈️

利用interceptors.response                        ,在业务代码获取到接口数据之前进行状态码401判断当前携带的accessToken是否失效。 下面是关于interceptors.response中异常阶段处理内容                   。当响应码为401时       ,响应拦截器会走中第二个回调函数onRejected

下面代码分段可能会让大家阅读起来不是很顺畅         ,我直接把整份代码贴在下面                       ,且每一段代码之间都添加了对应的注释

// 最大重发次数 const MAX_ERROR_COUNT = 5; // 当前重发次数 let currentCount = 0; // 缓存请求队列 const queue: ((t: string) => any)[] = []; // 当前是否刷新状态 let isRefresh = false; export default async (error: AxiosError<ResponseDataType>) => { const statusCode = error.response?.status; const clearAuth = () => { console.log(身份过期           ,请重新登录); window.location.replace(/login); // 清空数据 sessionStorage.clear(); return Promise.reject(error); }; // 为了节省多余的代码      ,这里仅展示处理状态码为401的情况 if (statusCode === 401) { // accessToken失效 // 判断本地是否有缓存有refreshToken const refreshToken = sessionStorage.get(refresh) ?? null; if (!refreshToken) { clearAuth(); } // 提取请求的配置 const { config } = error; // 判断是否refresh失败且状态码401                      ,再次进入错误拦截器 if (config.url?.includes(refresh)) { clearAuth(); } // 判断当前是否为刷新状态中(防止多个请求导致多次调refresh接口) if (!isRefresh) { // 设置当前状态为刷新中 isRefresh = true; // 如果重发次数超过               ,直接退出登录 if (currentCount > MAX_ERROR_COUNT) { clearAuth(); } // 增加重试次数 currentCount += 1; try { const { data: { access }, } = await UserAuthApi.refreshToken(refreshToken); // 请求成功   ,缓存新的accessToken sessionStorage.set(token, access); // 重置重发次数 currentCount = 0; // 遍历队列                     ,重新发起请求 queue.forEach((cb) => cb(access)); // 返回请求数据 return ApiInstance.request(error.config); } catch { // 刷新token失败                   ,直接退出登录 console.log(请重新登录); sessionStorage.clear(); window.location.replace(/login); return Promise.reject(error); } finally { // 重置状态 isRefresh = false; } } else { // 当前正在尝试刷新token,先返回一个promise阻塞请求并推进请求列表中 return new Promise((resolve) => { // 缓存网络请求                 ,等token刷新后直接执行 queue.push((newToken: string) => { Reflect.set(config.headers!, authorization, newToken); // @ts-ignore resolve(ApiInstance.request<ResponseDataType<any>>(config)); }); }); } } return Promise.reject(error); };

抽离代码

把上面关于调用刷新token的代码抽离成一个refreshToken函数                       ,单独处理这一情况   ,这样子做有利于提高代码的可读性和维护性             ,且让看上去代码不是很臃肿

// refreshToken.ts export default async function refreshToken(error: AxiosError<ResponseDataType>) { /* 将上面 if (statusCode === 401) 中的代码贴进来即可                        ,这里就不重复啦 代码仓库地址: https://github.com/QC2168/axios-bz/blob/main/Interceptors/hooks/refreshToken.ts */ }

经过上面的逻辑抽离       ,现在看下拦截器中的代码就很简洁了         ,后续如果要调整相关逻辑直接在refreshToken.ts文件中调整即可                    。

import refreshToken from ./refreshToken.ts export default async (error: AxiosError<ResponseDataType>) => { const statusCode = error.response?.status; // 为了节省多余的代码                       ,这里仅展示处理状态码为401的情况 if (statusCode === 401) { refreshToken() } return Promise.reject(error); };

本文转载于:

https://juejin.cn/post/7170278285274775560

如果对您有所帮助           ,欢迎您点个关注      ,我会定时更新技术文档                      ,大家一起讨论学习               ,一起进步    。

声明:本站所有文章   ,如无特殊说明或标注                     ,均为本站原创发布                。任何个人或组织                   ,在未征得本站同意时,禁止复制             、盗用                        、采集       、发布本站内容到任何网站         、书籍等各类媒体平台                    。如若本站内容侵犯了原著者的合法权益                 ,可联系我们进行处理        。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
echarts饼图位置调整(vue echarts饼图环形 (随着legend动态显示数据总数)) phpcms怎么样(phpcms作者名不显示怎么解决)