修正项目结构

This commit is contained in:
2026-05-31 04:46:30 +08:00
parent e69168775c
commit c2663c9ddd
7 changed files with 0 additions and 0 deletions
+274
View File
@@ -0,0 +1,274 @@
# 企业级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<String, Object> 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)