# Implementation Plan: Token 刷新机制 & 图形验证码 ## Overview 本任务清单实现两个安全增强功能:Token 刷新机制和图形验证码。采用增量开发方式,先完成后端 API,再更新前端。 ## Tasks - [x] 1. 创建 RefreshToken 数据库实体和迁移 - [x] 1.1 创建 RefreshToken 实体类 - 在 `Entities/` 目录创建 `RefreshToken.cs` - 包含 Id, AdminUserId, TokenHash, ExpiresAt, CreatedAt, CreatedByIp, RevokedAt, RevokedByIp, ReplacedByToken 字段 - 添加 IsExpired, IsRevoked, IsActive 计算属性 - _Requirements: 13.2_ - [x] 1.2 更新 AdminDbContext 配置 - 添加 DbSet - 配置实体映射和索引 - _Requirements: 13.2_ - [x] 1.3 创建数据库迁移脚本 - 创建 `Data/Migrations/add_refresh_tokens.sql` - 包含表创建和索引 - _Requirements: 13.2_ - [x] 2. 实现验证码服务 - [x] 2.1 创建验证码服务接口和实现 - 创建 `Services/ICaptchaService.cs` 接口 - 创建 `Services/CaptchaService.cs` 实现 - 使用 SkiaSharp 或 System.Drawing 生成图片 - 生成 4-6 位字母数字验证码 - 添加干扰线和噪点 - _Requirements: 14.2, 14.3_ - [x] 2.2 创建验证码请求/响应模型 - 创建 `Models/Auth/CaptchaResponse.cs` - 包含 CaptchaKey 和 CaptchaImage (base64) - _Requirements: 14.8_ - [x] 2.3 实现验证码缓存存储 - 使用 IMemoryCache 存储验证码 - 设置 5 分钟过期时间 - 实现验证后立即删除 - _Requirements: 14.3, 14.6_ - [x] 2.4 编写验证码服务单元测试 - 测试验证码格式(4-6位字母数字) - 测试验证码过期机制 - 测试单次使用约束 - **Property 10: Captcha code characteristics** - **Validates: Requirements 14.2** - [x] 3. 扩展认证服务支持 Token 刷新 - [x] 3.1 创建 Token 刷新相关模型 - 扩展 `LoginRequest` 添加 CaptchaKey, CaptchaCode - 扩展 `LoginResponse` 改 Token 为 AccessToken,添加 RefreshToken - 创建 `RefreshTokenRequest.cs` 和 `RefreshTokenResponse.cs` - _Requirements: 13.1_ - [x] 3.2 扩展 IAuthService 接口 - 添加 RefreshTokenAsync 方法 - 添加 RevokeTokenAsync 方法 - 添加 RevokeAllTokensAsync 方法 - _Requirements: 13.4, 13.6, 13.8_ - [x] 3.3 实现 RefreshToken 生成和存储 - 生成安全随机 Token - 哈希后存储到数据库 - 设置 7 天过期时间 - _Requirements: 13.1, 13.2_ - [x] 3.4 实现 Token 刷新逻辑 - 验证 RefreshToken 有效性 - 生成新的 AccessToken - 可选:轮换 RefreshToken - _Requirements: 13.4, 13.5_ - [x] 3.5 实现 Token 撤销逻辑 - 单个 Token 撤销(登出) - 用户所有 Token 撤销(强制下线) - _Requirements: 13.6, 13.8_ - [x] 3.6 修改登录逻辑集成验证码 - 验证码校验优先于密码校验 - 验证码错误不增加登录失败次数 - 登录成功后生成双 Token - _Requirements: 14.4, 14.5, 13.1_ - [x] 3.7 编写认证服务单元测试 - 测试验证码校验优先级 - 测试 Token 刷新逻辑 - 测试 Token 撤销逻辑 - **Property 12: Captcha validation before password check** - **Validates: Requirements 14.4, 14.5** - _Note: Tests written but xUnit discovery issue needs investigation_ - [x] 4. 更新 AuthController API - [x] 4.1 添加验证码获取接口 - `POST /api/admin/auth/captcha` - 返回 CaptchaKey 和 Base64 图片 - _Requirements: 14.8_ - [x] 4.2 添加 Token 刷新接口 - `POST /api/admin/auth/refresh` - 接收 RefreshToken,返回新 Token - _Requirements: 13.4_ - [x] 4.3 修改登录接口 - 接收验证码参数 - 返回双 Token - _Requirements: 13.1, 14.4_ - [x] 4.4 修改登出接口 - 撤销 RefreshToken - _Requirements: 13.6_ - [x] 4.5 添加强制下线接口(可选) - `POST /api/admin/auth/revoke-all` - 撤销用户所有 Token - _Requirements: 13.8_ - [x] 5. Checkpoint - 后端功能验证 - 确保所有后端 API 正常工作 - 使用 Postman/Swagger 测试接口 - 确保所有测试通过,如有问题请询问用户 - [x] 6. 更新前端 Token 管理 - [x] 6.1 扩展 auth.ts 工具函数 - 添加 AccessToken/RefreshToken 分离存储 - 添加 Token 过期时间存储 - 实现 isTokenExpiringSoon() 函数 - _Requirements: 13.3_ - [x] 6.2 扩展 auth API - 添加 getCaptcha() 接口 - 添加 refreshToken() 接口 - 更新 login() 请求/响应类型 - _Requirements: 13.1, 14.8_ - [x] 6.3 增强请求拦截器 - 实现自动 Token 刷新 - 防止并发刷新(Promise 锁) - 401 错误时尝试刷新 - _Requirements: 13.3, 13.4_ - [x] 6.4 编写前端工具函数测试 - 测试 isTokenExpiringSoon() 边界条件 - **Property 3: Token expiration detection** - **Validates: Requirements 13.3** - [x] 7. 更新登录页面 - [x] 7.1 添加验证码组件 - 显示验证码图片 - 添加刷新按钮 - 绑定验证码输入框 - _Requirements: 14.1, 14.7_ - [x] 7.2 更新登录表单 - 添加验证码字段验证规则 - 登录前获取验证码 - 登录失败后刷新验证码 - _Requirements: 14.4, 14.5_ - [x] 7.3 更新 user store - 存储双 Token - 更新登出逻辑 - _Requirements: 13.1, 13.6_ - [x] 8. 实现账号禁用时撤销 Token - [x] 8.1 修改 AdminUserService - 禁用账号时调用 RevokeAllTokensAsync - _Requirements: 13.7_ - [x] 9. Final Checkpoint - 完整功能验证 - 测试完整登录流程(验证码 → 登录 → 双Token) - 测试 Token 自动刷新 - 测试登出和强制下线 - 确保所有测试通过,如有问题请询问用户 ## Notes - 所有任务都是必须完成的,包括测试任务 - 每个任务都引用了具体的需求条款以便追溯 - Checkpoint 任务用于阶段性验证,确保增量开发的稳定性 - 验证码图片生成推荐使用 SkiaSharp(跨平台)或 System.Drawing.Common