Files
Uni_Login_system/doc/JWT_ENTERPRISE_GUIDE.md
2026-05-31 04:46:30 +08:00

7.8 KiB
Raw Permalink Blame History

企业级JWT加密方案使用指南

📋 概述

本项目已升级到企业级RSA-256 JWT加密方案,包含以下特性:

核心功能

  • 🔐 RSA-256非对称加密 - 私钥签名,公钥验证
  • 🔄 密钥轮换机制 - 支持无缝切换密钥
  • 🛡️ 防重放攻击 - JTI + Redis黑名单
  • 📝 增强Claims - ISS/AUD/NBF/JTI完整验证
  • ⚠️ 分类异常处理 - 精确的错误类型识别

🚀 快速开始

1. 生成RSA密钥对

运行密钥生成工具:

# 方式1: 直接运行Java类
java -cp target/classes com.caiji.uls.utils.jwt.RsaKeyGenerator

# 方式2: 运行测试类(推荐)
.\mvnw.cmd test-compile exec:java -Dexec.mainClass="com.caiji.uls.KeyGenTest"

生成的输出类似:

=== 生成RSA密钥对 ===

公钥 (Public Key):
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...

私钥 (Private Key):
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC...

=== 请将以上密钥配置到 application.properties ===
jwt.public-key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
jwt.private-key=MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC...

2. 配置密钥

将生成的密钥复制到 src/main/resources/application.properties

# JWT Configuration (Enterprise RSA-256)
jwt.public-key=你的公钥Base64字符串
jwt.private-key=你的私钥Base64字符串
jwt.expiration=86400000

3. 启动应用

.\mvnw.cmd spring-boot:run

启动成功后会看到:

[JWT] RSA密钥配置已初始化
[JWT] 过期时间: 86400000 毫秒 (1440 分钟)
[JWT] 签名算法: RS256 (RSA-SHA256)

💡 使用示例

生成Token

import com.caiji.uls.utils.jwt.JwtUtil;

// 基础用法
String token = JwtUtil.generateToken(userId, username);

// 带额外声明
Map<String, Object> claims = new HashMap<>();
claims.put("role", "admin");
claims.put("department", "IT");
String token = JwtUtil.generateToken(userId, username, claims);

验证Token

import com.caiji.uls.utils.jwt.JwtUtil;
import com.caiji.uls.utils.jwt.TokenBlacklistService;

@Autowired
private TokenBlacklistService blacklistService;

// 基础验证(仅验证签名和格式)
boolean isValid = JwtUtil.validateToken(token);

// 完整验证(包含黑名单检查)
boolean isValid = JwtUtil.validateToken(token, blacklistService);

// 提取用户信息
String userId = JwtUtil.getUserIdFromToken(token);
String username = JwtUtil.getUsernameFromToken(token);
String jti = JwtUtil.getJtiFromToken(token);

Token注销(加入黑名单)

@Autowired
private TokenBlacklistService blacklistService;

// 获取Token的JTI
String jti = JwtUtil.getJtiFromToken(token);

// 计算剩余有效期(秒)
long remainingTime = JwtUtil.getTokenRemainingTime(token);

// 加入黑名单
blacklistService.addToBlacklist(jti, remainingTime);

🔧 高级功能

密钥轮换

import com.caiji.uls.utils.jwt.JwtKeyManager;

// 生成新密钥对
var newKeyPair = RsaKeyGenerator.generateKeyPair();
String newPublicKey = RsaKeyGenerator.encodePublicKey((RSAPublicKey) newKeyPair.getPublic());
String newPrivateKey = RsaKeyGenerator.encodePrivateKey((RSAPrivateKey) newKeyPair.getPrivate());

// 执行轮换(旧密钥仍可用于验证)
JwtKeyManager.rotateKeys(newPublicKey, newPrivateKey);

// 过渡期后清除旧密钥(建议7-30天后)
JwtKeyManager.clearPreviousKey();

自定义Claims验证

import io.jsonwebtoken.Claims;

Claims claims = JwtUtil.getClaimsFromToken(token);

// 获取标准字段
String issuer = claims.getIssuer();        // 签发者
String audience = claims.getAudience();    // 受众
Date issuedAt = claims.getIssuedAt();      // 签发时间
Date expiration = claims.getExpiration();  // 过期时间

// 获取自定义字段
String userId = claims.get("userId", String.class);
String role = claims.get("role", String.class);

🛡️ 安全特性

1. RSA-256签名

  • 私钥签名:只有认证服务器持有私钥
  • 公钥验证:可分发公钥给多个微服务
  • 防篡改:任何修改都会导致签名验证失败

2. Claims增强

字段 说明 用途
iss 签发者 防止伪造Token
aud 受众 限制Token使用范围
nbf Not Before 防止时钟偏移攻击
jti JWT ID 唯一标识,防重放
iat Issued At 签发时间追踪
exp Expiration 自动过期

3. Redis黑名单

  • 即时注销:用户登出后立即失效
  • 密码修改保护:修改密码后所有Token失效
  • 自动清理Redis TTL自动删除过期条目

4. 异常分类

异常类型 HTTP状态码 说明
JwtTokenExpiredException 401 Token已过期
JwtSignatureInvalidException 401 签名无效
JwtMalformedException 400 格式错误
JwtTokenBlacklistedException 401 已被注销

⚙️ 配置项说明

# RSA公钥(Base64编码)
jwt.public-key=YOUR_PUBLIC_KEY

# RSA私钥(Base64编码,务必保密!)
jwt.private-key=YOUR_PRIVATE_KEY

# Token过期时间(毫秒),默认24小时
jwt.expiration=86400000

📊 架构优势对比

特性 旧版(HMAC 新版(RSA
加密算法 HS256对称加密 RS256非对称加密
密钥管理 单密钥硬编码 密钥对+轮换机制
多服务支持 需共享密钥 只需分发公钥
防重放攻击 JTI+黑名单
Claims验证 基础 ISS/AUD/NBF完整验证
密钥泄露风险 ⚠️ 低(私钥不泄露)
企业合规 不符合 符合OWASP标准

🔍 故障排查

问题1: 启动时提示"未检测到RSA密钥配置"

原因: application.properties中未配置密钥
解决: 运行密钥生成工具并配置密钥

问题2: Token验证失败"签名无效"

原因: 密钥不匹配或Token被篡改
解决:

  1. 确认公钥/私钥配置正确
  2. 检查Token是否完整传输
  3. 查看日志中的Key ID是否匹配

问题3: Redis连接失败

原因: Redis服务未启动或配置错误
解决: 检查application.properties中的Redis配置


📚 相关文件


🎯 最佳实践

  1. 生产环境必须配置固定密钥对,不要使用自动生成的临时密钥
  2. 私钥严格保密,不要提交到版本控制系统
  3. 定期轮换密钥(建议每30-90天)
  4. 监控黑名单大小,异常增长可能表示安全问题
  5. 设置合理的过期时间,平衡安全性和用户体验
  6. HTTPS传输,防止Token被中间人窃取

📞 技术支持

如有问题,请检查:

  1. 应用启动日志中的JWT初始化信息
  2. Redis连接状态
  3. 密钥配置是否正确
  4. Token格式是否符合JWT标准(三段式Base64)