# 企业级JWT加密方案使用指南 ## 📋 概述 本项目已升级到**企业级RSA-256 JWT加密方案**,包含以下特性: ### ✅ 核心功能 - 🔐 **RSA-256非对称加密** - 私钥签名,公钥验证 - 🔄 **密钥轮换机制** - 支持无缝切换密钥 - 🛡️ **防重放攻击** - JTI + Redis黑名单 - 📝 **增强Claims** - ISS/AUD/NBF/JTI完整验证 - ⚠️ **分类异常处理** - 精确的错误类型识别 --- ## 🚀 快速开始 ### 1. 生成RSA密钥对 运行密钥生成工具: ```bash # 方式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`: ```properties # JWT Configuration (Enterprise RSA-256) jwt.public-key=你的公钥Base64字符串 jwt.private-key=你的私钥Base64字符串 jwt.expiration=86400000 ``` ### 3. 启动应用 ```bash .\mvnw.cmd spring-boot:run ``` 启动成功后会看到: ``` [JWT] RSA密钥配置已初始化 [JWT] 过期时间: 86400000 毫秒 (1440 分钟) [JWT] 签名算法: RS256 (RSA-SHA256) ``` --- ## 💡 使用示例 ### 生成Token ```java import com.caiji.uls.utils.jwt.JwtUtil; // 基础用法 String token = JwtUtil.generateToken(userId, username); // 带额外声明 Map claims = new HashMap<>(); claims.put("role", "admin"); claims.put("department", "IT"); String token = JwtUtil.generateToken(userId, username, claims); ``` ### 验证Token ```java 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注销(加入黑名单) ```java @Autowired private TokenBlacklistService blacklistService; // 获取Token的JTI String jti = JwtUtil.getJtiFromToken(token); // 计算剩余有效期(秒) long remainingTime = JwtUtil.getTokenRemainingTime(token); // 加入黑名单 blacklistService.addToBlacklist(jti, remainingTime); ``` --- ## 🔧 高级功能 ### 密钥轮换 ```java 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验证 ```java 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 | 已被注销 | --- ## ⚙️ 配置项说明 ```properties # 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配置 --- ## 📚 相关文件 - **密钥生成**: [RsaKeyGenerator.java](file:///D:/ClassDev/Spring/uni_login_system/src/main/java/com/caiji/uls/utils/jwt/RsaKeyGenerator.java) - **密钥管理**: [JwtKeyManager.java](file:///D:/ClassDev/Spring/uni_login_system/src/main/java/com/caiji/uls/utils/jwt/JwtKeyManager.java) - **JWT工具**: [JwtUtil.java](file:///D:/ClassDev/Spring/uni_login_system/src/main/java/com/caiji/uls/utils/jwt/JwtUtil.java) - **黑名单服务**: [TokenBlacklistService.java](file:///D:/ClassDev/Spring/uni_login_system/src/main/java/com/caiji/uls/utils/jwt/TokenBlacklistService.java) - **配置初始化**: [JwtConfigInitializer.java](file:///D:/ClassDev/Spring/uni_login_system/src/main/java/com/caiji/uls/config/JwtConfigInitializer.java) - **异常处理**: [JwtGlobalExceptionHandler.java](file:///D:/ClassDev/Spring/uni_login_system/src/main/java/com/caiji/uls/config/JwtGlobalExceptionHandler.java) --- ## 🎯 最佳实践 1. **生产环境必须配置固定密钥对**,不要使用自动生成的临时密钥 2. **私钥严格保密**,不要提交到版本控制系统 3. **定期轮换密钥**(建议每30-90天) 4. **监控黑名单大小**,异常增长可能表示安全问题 5. **设置合理的过期时间**,平衡安全性和用户体验 6. **HTTPS传输**,防止Token被中间人窃取 --- ## 📞 技术支持 如有问题,请检查: 1. 应用启动日志中的JWT初始化信息 2. Redis连接状态 3. 密钥配置是否正确 4. Token格式是否符合JWT标准(三段式Base64)