前端无感刷新token机制(一文说明白)

news/2024/12/22 12:28:46/

前言

用户登录之后,会返回一个用户的标识,之后带上这个标识请求别的接口,就能识别出该用户。

标识登录状态的方案有两种: session 和 jwt。这两种方案一个服务端存储,通过 cookie 携带标识,一个在客户端存储,通过 header 携带标识。

session 是通过 cookie 返回一个 id,关联服务端内存里保存的 session 对象,请求时服务端取出 cookie 里 id 对应的 session 对象,就可以拿到用户信息。

在这里插入图片描述

jwt 不在服务端存储,会直接把用户信息放到 token 里返回,每次请求带上这个 token,服务端就能从中取出用户信息。

session 的方案默认不支持分布式,因为是保存在一台服务器的内存的,另一台服务器没有。jwt 的方案天然支持分布式,因为信息保存在 token 里,只要从中取出来就行。

为什么需要无感刷新token机制

服务端把用户信息放入 token 里,设置一个过期时间,客户端请求的时候通过 authorization 的 header 携带 token,服务端验证通过,就可以从中取到用户信息。

但是token 是有过期时间的,比如 3 天,那过期后再访问就需要重新登录了。这样体验并不好。
想想你在用某个 app 的时候,用着用着突然跳到登录页了,告诉你需要重新登录了。是不是体验很差?

所以要加上续签机制,也就是延长 token 过期时间。

主流的方案是通过双 token,一个 access_token、一个 refresh_token(一个短token,一个长token)。

无感刷新token机制

用户登录成功之后,两个 token(一个 access_token、一个 refresh_token),访问接口时携带 access_token 访问,当 access_token 过期时,通过 refresh_token 来刷新,拿到新的 access_token 和 refresh_token。

而 access_token 一般过期时间设置的比较短,比如 30 分钟,refresh_token 设置的过期时间比较长,比如 7 天。这样,只要你 7 天内访问一次,就能刷新 token,再续 7 天,一直不需要登录。

但如果你超过 7 天没访问,那 refresh_token 也过期了,就需要重新登录了。想想你常用的 APP,是不是没再重新登录过?而不常用的 APP,再次打开是不是就又要重新登录了?这种一般都是双 token 做的。

实现

在axios的响应拦截器中刷新token。

这里还需要排除下 /refresh 接口,也就是刷新失败不继续刷新,不然会进入死循环。

刷新 token 成功,就重发之前的请求,否则,提示重新登录。其他错误直接返回。

在刷新 token 的接口里,拿到新的 access_token 和 refresh_token 后,更新本地存储的 token。

axiosInstance.interceptors.response.use((response) => {return response;},async (error) => {let { data, config } = error.response;if (data.statusCode === 401 && !config.url.includes('/refresh')) {const res = await refreshToken();if(res.status === 200) {return axiosInstance(config);} else {alert(data || '登录过期,请重新登录');}} else {return error.response;}}
)async function refreshToken() {const res = await axiosInstance.get('/refresh', {params: {token: localStorage.getItem('refresh_token')}});localStorage.setItem('access_token', res.data.accessToken);localStorage.setItem('refresh_token', res.data.refreshToken);return res;
}

但是还有一些问题,如果并发请求,多次调用后端接口,会刷新token多次,解决方案如下:

加一个 refreshing 的标记,记录是否正在刷新token,如果在刷新,那就返回一个 promise,并且把它的 resolve 方法还有 config 加入到一个队列里。

当 token刷新 成功之后,重新发送队列中的请求(即在刷新期间积压的请求),并且把结果通过 resolve 返回(即重新发起请求)。

interface PendingTask {config: AxiosRequestConfigresolve: Function
}let refreshing = false;
const queue: PendingTask[] = [];axiosInstance.interceptors.response.use((response) => {return response;},async (error) => {let { data, config } = error.response;if(refreshing) {return new Promise((resolve) => {queue.push({config,resolve});});}if (data.statusCode === 401 && !config.url.includes('/refresh')) {refreshing = true;const res = await refreshToken();refreshing = false;if(res.status === 200) {queue.forEach(({config, resolve}) => {resolve(axiosInstance(config))})return axiosInstance(config);} else {alert(data || '登录过期,请重新登录');}} else {return error.response;}}
)axiosInstance.interceptors.request.use(function (config) {const accessToken = localStorage.getItem('access_token');if(accessToken) {config.headers.authorization = 'Bearer ' + accessToken;}return config;
})

http://www.ppmy.cn/news/1557188.html

相关文章

DA-CLIP:Controlling Vision-Language Models for Universal Image Restoration

conference:2024 ICLR paper:https://arxiv.org/pdf/2310.01018 code:https://github.com/Algolzw/daclip-uir 文章目录 作者动机核心思想常见解决方案挑战本文解决方法 贡献方法基本框架Controller的优化与Loss函数数据对的生成基本框架数据…

windwos defender实现白名单效果(除了指定应用或端口其它一律禁止)禁止服务器上网

一、应用场景说明 当我们的一台windows服务器中毒,变成别人肉鸡,不断向外请示非法网站或攻击其它服务器。 要彻底清除相关木马或病毒往往需要的时间比较长,比较有效的方法是禁止服务器主动向外发包除了网站端口和远程程序除外。 其实这就是一…

#渗透测试#漏洞挖掘#红蓝攻防#SRC漏洞挖掘05之并发漏洞挖掘技巧

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 目录 并发漏洞 1、刷赞 2、签到 3、突破限购 …

excel 使用vlook up找出两列中不同的内容

当使用 VLOOKUP 函数时,您可以将其用于比较两列的内容。假设您要比较 A 列和 B 列的内容,并将结果显示在 C 列,您可以在 C1 单元格中输入以下公式: 这个公式将在 B 列中的每个单元格中查找是否存在于 A 列中。如果在 A 列中找不到…

半导体制造技术导论(第二版)萧宏 第十二章 化学机械研磨工艺

本章要求 1.列出化学机械研磨工艺的应用 化学机械研磨是一种移除工艺技术,结合化学反应和机械研磨去除沉积的薄膜,使表面更加平滑和平坦;也用于移除表面上大量的电介质薄膜,并在硅衬底上形成浅沟槽隔离STI;还可以从晶圆…

CSS系列(21)-- Houdini 详解

前端技术探索系列:CSS Houdini 详解 🎨 致读者:探索 CSS 的新边界 👋 前端开发者们, 今天我们将深入探讨 CSS Houdini,这项革命性的技术让我们能够直接访问 CSS 引擎的底层。 Houdini 基础 &#x1f68…

【已解决】【大数据综合案例】上| Hive与MongoDB配置

遇到的问题及解决方法 Hive 报错:sudo: 未知用户;HiveServer2启动失败;端口被占用 导入数据:通过JDBC连接Hive和MySQL,将数据从Hive导入MySQL。通过JDBC连接Hive,需要通过Hive的thrift服务实现跨语言访问…

基于“2+1 链动模式商城小程序”的微商服务营销策略探究

摘要:本文探讨在竞争激烈的市场经济与移动互联网时代背景下,微商面临的机遇与挑战。着重分析“21 链动模式商城小程序”如何助力微商改变思路,通过重视服务、提升服务质量,以服务营销放大利润,实现从传统微商模式向更具…