7.8 KiB
7.8 KiB
企业级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被篡改
解决:
- 确认公钥/私钥配置正确
- 检查Token是否完整传输
- 查看日志中的Key ID是否匹配
问题3: Redis连接失败
原因: Redis服务未启动或配置错误
解决: 检查application.properties中的Redis配置
📚 相关文件
- 密钥生成: RsaKeyGenerator.java
- 密钥管理: JwtKeyManager.java
- JWT工具: JwtUtil.java
- 黑名单服务: TokenBlacklistService.java
- 配置初始化: JwtConfigInitializer.java
- 异常处理: JwtGlobalExceptionHandler.java
🎯 最佳实践
- 生产环境必须配置固定密钥对,不要使用自动生成的临时密钥
- 私钥严格保密,不要提交到版本控制系统
- 定期轮换密钥(建议每30-90天)
- 监控黑名单大小,异常增长可能表示安全问题
- 设置合理的过期时间,平衡安全性和用户体验
- HTTPS传输,防止Token被中间人窃取
📞 技术支持
如有问题,请检查:
- 应用启动日志中的JWT初始化信息
- Redis连接状态
- 密钥配置是否正确
- Token格式是否符合JWT标准(三段式Base64)