token无感刷新+处理并发的后端方案
问题描述:
当用户通过登陆后进入一个web网站,会把token保存到localStorage。假设token过期时间30min。
那么当用户在网站快乐地玩耍了30min后,这时进行了一次提交表单,它会被重定向到登陆页面。
作为用户:我表单填了这么久,点击提交时让我重新登陆?我的体验很不好。
jwt的好处和局限
jwt的好处是:服务器无需存储这些登陆的状态
而它的局限是:服务器无法主动地通知用户“你的token过期了,我重新给你一个”。
如何解决
方案一:双token
在登陆时我们会生成俩个token
- token:表示正常情况下登陆凭证
- refresh-token:表示需要刷新情况下登陆凭证
假设前者(token)设置过期时间为30min,后者为1天。
流程
- time=0min,用户成功登陆,后端返回俩个token(token和refresh-token),前端把它俩保存到localStorage
- time=10min,用户进行了一次查询,前端将俩个token都发给后端,后端检验token,有效,返回结果,用户很开心!
- time=35min,用户提交了表单,前端还是将俩个token发给后端;后端检验token,过期;检验refresh-token,有效,后端认为这是要刷新token,生成新的token和refresh-token,成功返回数据和双token。前端把数据渲染,把双token保存。
token正常过期的情况:
当然,token可以正常过期,如果在检验时refresh-token也过期,那就说明正常过期
假设time=0min时用户登陆,time=2天时用户提交了表单,那么后端认为这是正常过期,用户需要重新登陆。
流程图如下:

token刷新并发问题
现在很多登陆是可以多端的,当多端并发都去尝试刷新token时,会导致token被重复刷新
方案二:刷新时用分布式锁
可以引入redis缓存中间件,使用缓存加速并处理并发刷新问题。
将双token生成后存入redis。当需要刷新token时,采用double-check+获取关于refresh-token的分布式锁来实现。
伪代码如下:
// 验证和刷新Token的方法
public String validateAndRefreshToken(String userId, String accessToken, String refreshToken) {
String storedAccessToken = redisTemplate.opsForValue().get(ACCESS_TOKEN_PREFIX + userId);
String storedRefreshToken = redisTemplate.opsForValue().get(REFRESH_TOKEN_PREFIX + userId);// 检查Access Token是否有效
if (storedAccessToken != null && storedAccessToken.equals(accessToken)) {
return accessToken; // 直接返回原始的Access Token
}// Access Token无效,检查Refresh Token
if (storedRefreshToken != null && storedRefreshToken.equals(refreshToken)) {
// 使用双层检查和分布式锁控制高并发刷新
String lockKey = "refresh_lock:" + userId;
boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.SECONDS);
if (lockAcquired) {
try {
// 再次双层检查(避免重复刷新)
storedAccessToken = redisTemplate.opsForValue().get(ACCESS_TOKEN_PREFIX + userId);
if (storedAccessToken == null) {
// 生成新的Access Token
String newAccessToken = generateToken();
redisTemplate.opsForValue().set(ACCESS_TOKEN_PREFIX + userId, newAccessToken, 15, TimeUnit.MINUTES);
return newAccessToken;
} else {
return storedAccessToken; // 直接返回已刷新过的Token
}
} finally {
redisTemplate.delete(lockKey); // 释放锁
}
} else {
// 未获取到锁,等待其他线程刷新完成,再次获取已刷新的Access Token
return redisTemplate.opsForValue().get(ACCESS_TOKEN_PREFIX + userId);
}
}// 若Refresh Token也无效,返回null或抛出异常,需重新登录
throw new TokenInvalidException("Access and Refresh Token both expired.");
}
方案三:过渡时间(没看懂)

相关文章:
token无感刷新+处理并发的后端方案
问题描述: 当用户通过登陆后进入一个web网站,会把token保存到localStorage。假设token过期时间30min。 那么当用户在网站快乐地玩耍了30min后,这时进行了一次提交表单,它会被重定向到登陆页面。 作为用户:我表单填了…...
【系统设计】让 Java “动起来”:动态语言与静态语言的比较及 DSL 实现
在编程语言的世界里,语言的特性决定了它们在不同场景下的适用性。动态语言和静态语言是两种常见的编程范式,它们的差异不仅影响开发者的使用习惯,还决定了它们在某些应用场景中的表现。在这篇博文中,我们将通过Python和Java这两种…...
TCP Analysis Flags 之 TCP Keep-Alive
前言 默认情况下,Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态,并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时,会对每个 TCP 数据包进行一次分析,数据包按照它们在数据包列表中出现的顺序进行处理。可…...
mfc140u.dll丢失怎么办? mfc140u.dll文件缺失的修复技巧
mfc140u.dll 是 Microsoft Foundation Classes (MFC) 库的一部分,它是 Visual Studio 2015 的组件之一,主要服务于使用 C 编写的 Windows 应用程序。这个动态链接库文件包含了 MFC 14.0 Unicode 版本的实现代码,为应用程序提供运行时支持。当…...
Spring Security使用
文章目录 Spring Security的起点FilterChain重写重写登录验证逻辑增加CSRF Token增加方法权限校验 Spring Security的起点 在AbstractApplicationContext.refresh()方法时,子类ServletWebServerApplicationContext会创建一个ServletContextInitializerBeans这个Bea…...
CSS网页布局综合练习(涵盖大多CSS知识点)
该综合练习就是为这个学校静态网页设置CSS样式,使其变成下面的模样 其基本骨架代码为: <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta name"viewport" content…...
解决 Hardhat Verify 超时
问题背景 今天在学习使用Hardhat进行verify 合约 到 Ethscan的时候,出现了如下报错 fafafafadeMacBook-Air Web3_Solidity_Study % npx hardhat verify --network sepolia XXXXXXXXXXXXXXXXXXXXXXXX "10" Successfully verifie…...
ACIS创建各种基本体,举例说明
ACIS(Advanced CAD Interoperability System)是一个广泛使用的三维几何建模内核,它支持创建和操作各种基本的三维几何体。虽然ACIS没有专门的函数来直接创建某些特定的基本体(如椭球体),但可以通过一系列变…...
[CISCN 2019华北]PWN1-好久不见7
Partial RELRO 表示部分 RELRO 保护已启用。在这种情况下,只有某些部分(如 GOT 中的只读部分)是只读的。 NX enabled 表示这个二进制文件启用了 NX 保护,数据段是不可执行的。这可以防止某些类型的代码注入攻击。 这里是ida识别…...
代码随想录day16| 513找树左下角的值 、 路径总和 、 从中序与后序遍历序列构造二叉树
代码随想录day16| 找树左下角的值 、 路径总和 、 从中序与后序遍历序列构造二叉树 513找树左下角的值层序遍历法递归法 路径总和112. 路径总和113. 路径总和 II 从中序与后序遍历序列构造二叉树思路 513找树左下角的值 层序遍历法 使用层序遍历,找到最后一层最左边…...
使用 MMDetection 实现 Pascal VOC 数据集的目标检测项目练习(二) ubuntu的下载安装
首先,Linux系统是人工智能和深度学习首选系统。原因如下: 开放性和自由度:Linux 是一个开源操作系统,允许开发者自由修改和分发代码。这在开发和研究阶段非常有用,因为开发者可以轻松地访问和修改底层代码。社区支持:…...
书生大模型实战营(第四期)——入门岛
第 1 关 Linux 前置基础 闯关任务完成SSH连接与端口映射并运行hello_world.py10min可选任务 1将Linux基础命令在开发机上完成一遍10min可选任务 2使用 VSCODE 远程连接开发机并创建一个conda环境10min 完成SSH连接 创建python文件 建环境 运行 第 2 关 Python 前置基础 Leet…...
压强随着时间的变化
import numpy as np import matplotlib.pyplot as plt# 参数设置 L 50 # 长度 (m) D 4 # 直径 (m) d 0.01 # 洞的直径 (m) P0 101300 # 初始压力 (Pa) P_final 0.3 * P0 # 最终压力 (Pa) R 287 # 理想气体常数 (J/(kgK)) T 20 273.15 # 温度 (K) M 0.029 # 空…...
2024年大厂AI大模型面试题精选与答案解析
前言 随着AI市场,人工智能的爆火,在接下来的金九银十招聘高峰期,各大科技巨头和国有企业将会对AGI人才的争夺展开一场大战,为求职市场注入了新的活力。 为了助力求职者在面试中展现最佳状态,深入理解行业巨头的选拔标…...
Linux开发讲课47--- 详解 Linux 中的虚拟文件系统
虚拟文件系统是一种神奇的抽象,它使得 “一切皆文件” 哲学在 Linux 中成为了可能。 什么是文件系统?根据早期的 Linux 贡献者和作家 Robert Love 所说,“文件系统是一个遵循特定结构的数据的分层存储。” 不过,这种描述也同样适用…...
全球银行常用英语
Earn OCBC$ or 90 Miles or VOYAGE Miles today! Get the most out of your OCBC Card with OCBC Privileges. 今天赚取华侨银行美元或 90 英里或航程英里!通过华侨银行特权充分利用您的华侨银行卡。 Check out the rewards catalogue. Apply for a OCBC Credit Car…...
新160个crackme -090-tc.12
运行分析 需要破解注册码 PE分析 Delphi程序,32位,无壳 静态分析&动态调试 ida搜不到字符串,根据Deiphi程序的结构,直接打开来到start函数,找到CreateForm函数的参数off_445FC4,双击 逐个查找偏移&…...
Swagger文档-Unable to scan documentation context default报错
文章目录 报错情况: Unable to scan documentation context 管理端接口发生情况一:发生情况三: 报错情况: Unable to scan documentation context 管理端接口 报错日志: 2024-11-03 12:40:27.427 ERROR 3340 --- [ …...
SpringKafka生产者、消费者消息拦截
1 前言 在Spring Kafka中,可以通过配置拦截器来实现对生产者和消费者消息的拦截。拦截器可以用来记录日志、修改消息等等。 2 基于Kafka管理的拦截器 Kafka原生提供的拦截器接口是org.apache.kafka.clients.producer.ProducerInterceptor和 org.apache.kafka.cli…...
Qt报错QOCI driver not loaded且QOCI available的解决方法
参考 Linux Qt 6安装Oracle QOCI SQL Driver插件(适用WSL) 安装 QOCI 插件完成后运行 Qt 项目报错: qt.sql.qsqldatabase: QSqlDatabase: QOCI driver not loaded qt.sql.qsqldatabase: QSqlDatabase: available drivers: QMIMER QPSQL QODBC…...
BiLSTM时间序列预测实战:用Python搞定股票价格预测(附完整代码)
BiLSTM金融时间序列预测:从理论到实战的Python完整指南 金融市场如同汹涌的海浪,价格波动背后隐藏着无数投资者的决策与情绪。对于量化分析师和算法交易者而言,准确预测这些波动意味着巨大的商业价值。传统的时间序列分析方法如ARIMA在面对非…...
Windows主题自由革命:SecureUxTheme安全启动兼容的内存补丁终极指南
Windows主题自由革命:SecureUxTheme安全启动兼容的内存补丁终极指南 【免费下载链接】SecureUxTheme 🎨 A secure boot compatible in-memory UxTheme patcher 项目地址: https://gitcode.com/gh_mirrors/se/SecureUxTheme 厌倦了Windows千篇一律…...
StructBERT情感分类实操手册:自定义示例文本添加方法
StructBERT情感分类实操手册:自定义示例文本添加方法 1. 引言:为什么需要自定义示例? 当你第一次打开StructBERT情感分类的Web界面,可能会觉得它已经内置了不少例子,用起来挺方便。但用着用着,你就会发现…...
网络异常排查:快速定位域连接问题
问题描述与初步排查网络位置异常通常表现为计算机无法正确识别当前所在的AD域环境,导致访问域资源受限或登录问题。常见症状包括系统托盘显示“无法访问域”、组策略无法应用、DNS解析失败等。检查计算机是否能够ping通域控制器的主机名和IP地址。使用nslookup命令验…...
手把手教你用Wireshark抓包分析Opener EIP通信,快速定位ForwardOpen失败原因
深度解析EtherNet/IP通信:用Wireshark诊断ForwardOpen失败的实战指南 当你在MCU上成功移植了Opener协议栈,TCP连接建立正常,却在关键时刻遭遇ForwardOpen失败时,那种挫败感我深有体会。去年在汽车生产线控制系统项目中,…...
GLM-4v-9b行业落地:跨境电商商品图多语言描述生成自动化方案
GLM-4v-9b行业落地:跨境电商商品图多语言描述生成自动化方案 1. 引言:跨境电商卖家的共同痛点 如果你是做跨境电商的,下面这个场景你一定不陌生:仓库里堆满了新品,运营同事催着要上架,但每个商品都需要准…...
【OFDM通信】基于matlab室内NOMA-OFDM-VLC系统仿真【含Matlab源码 15240期】
💥💥💥💥💥💥💞💞💞💞💞💞💞💞欢迎来到海神之光博客之家💞💞💞Ὁ…...
SillyTavern角色卡片系统全解析:从技术原理到实战应用
SillyTavern角色卡片系统全解析:从技术原理到实战应用 【免费下载链接】SillyTavern LLM Frontend for Power Users. 项目地址: https://gitcode.com/GitHub_Trending/si/SillyTavern 技术原理:PNG元数据驱动的角色存储机制 SillyTavern角色卡片…...
若依框架下,如何让JimuReport积木报表乖乖认你的登录状态?(附完整前后端代码)
若依框架与JimuReport深度整合:实现无缝登录状态管理的全链路实践 在当今企业级应用开发中,权限控制与单点登录已成为基础需求。当我们将若依(RuoYi)这一流行后台管理系统框架与JimuReport报表工具集成时,如何确保两者间的登录状态无缝衔接&a…...
ESP8266 AT指令实战:用NodeMCU连接WiFi并发送HTTP请求(2023最新版)
ESP8266 AT指令实战:用NodeMCU连接WiFi并发送HTTP请求(2023最新版) 当你拿起一块NodeMCU开发板时,它可能看起来只是块普通的电路板,但内置的ESP8266芯片让它成为了物联网开发的瑞士军刀。不同于Arduino需要额外WiFi模块…...
