当前位置: 首页 > news >正文

SpringBoot3集成Oauth2.1——10重启程序Token失效(RSA持久化)

每次颁发的token,在重启以后,有小伙伴可能说想,是不是token使用内存存储,重启以后token就没了,其实不是这样,这个和之前的老版本的Oauth2不一样。因此并不是因为存储失效了,导致JWT失效。

特性JWT传统随机字符串 Token
信息载体自包含(Payload 带用户/有效期信息)仅为随机字符串(无实际含义)
服务端存储需求无需存储 Token,仅存密钥必须存储 Token(如 Redis/数据库),并关联用户信息
验证逻辑本地验证(密钥+签名对比)需查存储系统(验证 Token 是否存在、关联用户是否合法)
扩展性(分布式场景)天然支持(无状态,服务端可水平扩展)需共享存储(如 Redis 集群),否则多服务节点无法验证

具体来说,如果系统采用 “本地生成 RSA 密钥对” 的模式(例如授权服务器自己生成 RSA 密钥对用于签名 JWT,或资源服务器持有本地 RSA 公钥用于验证签名),而这些密钥对仅存在内存中、未持久化到磁盘或安全存储(如密钥管理服务 KMS),那么程序重启后:

1.授权服务器会重新生成新的 RSA 密钥对,导致之前用旧密钥签名的 Token 全部失效(验证时签名不匹配);
2.资源服务器的JWKSource会丢失之前的 RSA 公钥,无法验证重启前签发的 Token(找不到对应的验证密钥)

如下所示,每次我们都是重新创建keyPair,并且每次的KeyID都是从新生成的UUID,因此,也就是我们上面所说的问题。

/** @Description: 创建用于JWT签名和验证的JWK源,生成RSA密钥对并构建JWK集合,用于OAuth2授权服务器* @author: 胡涛* @mail: hutao_2017@aliyun.com* @date: 2025年5月27日 上午11:46:45*/@Beanpublic JWKSource<SecurityContext> jwkSource() {KeyPair keyPair = generateRsaKey();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();RSAKey rsaKey = new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();JWKSet jwkSet = new JWKSet(rsaKey);return new ImmutableJWKSet<>(jwkSet);}/** @Description: 生成RSA密钥对,密钥长度为2048位* @author: 胡涛* @mail: hutao_2017@aliyun.com* @date: 2025年5月20日 上午10:47:00*/private static KeyPair generateRsaKey() {KeyPair keyPair;try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);keyPair = keyPairGenerator.generateKeyPair();}catch (Exception ex) {throw new IllegalStateException(ex);}return keyPair;}
}

现在我们微调代码如下

  1. 调整1:固定 RSAKey 的 keyID
  2. 调整2:持久化 KeyPair
	private static final String KEY_ID = "oauth2-rsa-key-pair.ser";@Beanpublic JWKSource<SecurityContext> jwkSource() {KeyPair keyPair = generateRsaKey();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();RSAKey rsaKey = new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(KEY_ID)//调整1 KEY_ID 固定.build();JWKSet jwkSet = new JWKSet(rsaKey);return new ImmutableJWKSet<>(jwkSet);}private static KeyPair generateRsaKey() {//调整2 从文件获取File file = new File(KEY_ID);if (file.exists() && file.length() > 0) {try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {return (KeyPair) ois.readObject();} catch (Exception e) {e.printStackTrace();}}//如果文件不存在,则新建KeyPairGenerator keyPairGenerator;KeyPair keyPair = null;try {keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);keyPair = keyPairGenerator.generateKeyPair();ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(KEY_ID));oos.writeObject(keyPair);oos.close();} catch (Exception e) {e.printStackTrace();}return keyPair;}

最后,在程序运行的相对根目录就会产生密钥对文件
在这里插入图片描述

http://www.dtcms.com/a/349831.html

相关文章:

  • Java项目-苍穹外卖_Day1
  • Visual Studio 2022调试Eigen库查看矩阵与向量的值
  • 大模型知识点之矩阵乘以向量
  • springboot:前后端调用(axios发送异步请求)
  • 那我现在有3个输入 9层神经元 每层神经元数为 3 9 3 5 6 2 3 9 8 请给出我所有的权重矩阵
  • 图论水题5
  • ansible的搭建与安装
  • BIO、NIO 和 AIO
  • 智慧城市SaaS平台/交通设施运行监测系统之桥梁运行监测、城市道路塌陷风险运行监测系统架构内容
  • v-slot 与 slot-scope区别
  • 开源零信任本地化部署实战指南:Keycloak + OpenZiti 完整方案
  • [element-plus] el-table在行单击时获取行的index
  • JAVA高级工程师--云服务模式多租户SAAS项目商业模式架构全景
  • 【数据可视化-98】2025年上半年地方财政收入Top 20城市可视化分析:Python + Pyecharts打造炫酷暗黑主题大屏
  • 【Java基础】快速掌握Java泛型机制:基本概念与具体应用
  • 工具系列:JsonViewKit
  • Frida 加密解密算法实现与应用指南
  • kafka 原理详解
  • 代码随想录算法训练营30天 | ​​01背包理论基础、416. 分割等和子集
  • Radxa Rock 5B vs Rock 5B+ 、香橙派、鲁班猫、正点原子及RK3588 的AI/音视频任务的选择
  • springboot项目每次启动关闭端口仍被占用
  • 第 93 场周赛:二进制间距、重新排序得到 2 的幂、优势洗牌、最低加油次数
  • Agent实战教程:LangGraph相关概念介绍以及快速入门
  • Reachability Query
  • 算法每日一题 | 入门-分支结构-肥胖问题
  • 【modbus学习】野火Modbus主机接收到数据后的完整函数调用流程
  • Ajax笔记(上)
  • Vue3在一个对象的list中,找出update_date最大的一条数据
  • MCP 协议原理与系统架构详解—从 Server 配置到 Client 应用
  • vscode--快捷键