HaniBlindBox/.kiro/specs/refresh-token/tasks.md
2026-01-25 19:10:31 +08:00

143 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementation Plan: Refresh Token 机制
## Overview
实现双 Token 认证机制,分为后端改动和前端改动两个阶段。后端先完成数据库、实体、服务和接口的改动,前端再实现自动刷新逻辑。
## Tasks
- [x] 1. 后端:数据库和实体层
- [x] 1.1 创建 UserRefreshToken 实体类
-`HoneyBox.Model/Entities/` 目录下创建 `UserRefreshToken.cs`
- 包含 Id、UserId、TokenHash、ExpiresAt、CreatedAt、CreatedByIp、RevokedAt、RevokedByIp、ReplacedByToken 字段
- 添加计算属性 IsExpired、IsRevoked、IsActive
- 添加与 User 表的外键关联
- _Requirements: 5.1, 5.2_
- [x] 1.2 更新 DbContext 添加 UserRefreshTokens DbSet
-`HoneyBoxDbContext.cs` 中添加 `DbSet<UserRefreshToken> UserRefreshTokens`
- 配置表名和索引
- _Requirements: 5.1_
- [x] 1.3 创建数据库迁移脚本
- 创建 `create_user_refresh_tokens.sql` 脚本
- 包含表创建、索引和外键约束
- _Requirements: 5.1, 5.2_
- [x] 2. 后端:模型和接口层
- [x] 2.1 创建 LoginResponse 模型
-`HoneyBox.Model/Models/Auth/` 目录下创建 `LoginResponse.cs`
- 包含 AccessToken、RefreshToken、ExpiresIn 字段
- _Requirements: 1.1, 1.2_
- [x] 2.2 创建 RefreshTokenRequest 和 RefreshTokenResult 模型
- 创建请求模型包含 RefreshToken 字段
- 创建结果模型包含 Success、LoginResponse、ErrorMessage 字段
- _Requirements: 2.1_
- [x] 2.3 扩展 IAuthService 接口
- 添加 `RefreshTokenAsync` 方法
- 添加 `RevokeTokenAsync` 方法
- 添加 `RevokeAllUserTokensAsync` 方法
- _Requirements: 2.1, 4.4_
- [-] 3. 后端:服务层实现
- [x] 3.1 实现 Refresh Token 生成和存储逻辑
- 在 AuthService 中添加 `GenerateRefreshToken` 私有方法
- 使用 SHA256 哈希存储 Token
- 设置 7 天有效期
- _Requirements: 1.4, 1.5, 4.1_
- [x] 3.2 修改登录方法返回双 Token
- 修改 `WechatMiniProgramLoginAsync` 返回 LoginResponse
- 修改 `MobileLoginAsync` 返回 LoginResponse
- 调用 GenerateRefreshToken 生成并存储 Refresh Token
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5_
- [x] 3.3 实现 RefreshTokenAsync 方法
- 验证 Refresh Token 有效性(未过期、未撤销)
- 实现 Token 轮换(撤销旧 Token生成新 Token
- 记录 ReplacedByToken 关联关系
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 5.3_
- [x] 3.4 实现 RevokeTokenAsync 方法
- 根据 Token 哈希查找并撤销
- 记录撤销时间和 IP
- _Requirements: 4.4_
- [ ]* 3.5 编写属性测试:登录响应结构完整性
- **Property 1: 登录响应结构完整性**
- **Validates: Requirements 1.1, 1.2**
- [ ]* 3.6 编写属性测试Token 轮换完整性
- **Property 6: Token 轮换完整性**
- **Validates: Requirements 2.5, 2.6**
- [x] 4. Checkpoint - 后端服务层完成
- 确保所有测试通过ask the user if questions arise.
- [x] 5. 后端:控制器层
- [x] 5.1 修改 AuthController 登录接口返回格式
- 修改 `WechatMiniProgramLogin` 返回 `ApiResponse<LoginResponse>`
- 修改 `MobileLogin` 返回 `ApiResponse<LoginResponse>`
- 保持向后兼容(同时返回 token 字段)
- _Requirements: 1.1, 1.2, 6.1_
- [x] 5.2 新增 Token 刷新接口
- 添加 `POST /api/refresh` 端点
- 接收 RefreshTokenRequest返回 LoginResponse
- 处理各种错误情况
- _Requirements: 2.1, 2.2, 2.3, 2.4_
- [x] 5.3 新增 Token 撤销接口(可选,用于退出登录)
- 添加 `POST /api/logout` 端点
- 撤销用户的 Refresh Token
- _Requirements: 4.4_
- [x] 6. Checkpoint - 后端完成
- 确保所有测试通过ask the user if questions arise.
- 使用 Postman 或 curl 测试接口
- [x] 7. 前端Token 存储改造
- [x] 7.1 修改登录成功后的 Token 存储逻辑
- 存储 accessToken 和 refreshToken 到 uni.storage
- 计算并存储 tokenExpireTime
- _Requirements: 4.2_
- [x] 7.2 修改退出登录清除 Token 逻辑
- 清除 accessToken、refreshToken、tokenExpireTime
- 调用后端撤销接口(可选)
- _Requirements: 4.3_
- [x] 8. 前端:自动刷新机制
- [x] 8.1 实现 refreshToken 方法
- 调用 `/api/refresh` 接口
- 更新本地存储的 Token
- 返回刷新结果
- _Requirements: 3.1, 3.2_
- [x] 8.2 实现请求队列机制
- 添加 isRefreshing 状态标记
- 添加 refreshQueue 请求队列
- 刷新完成后依次执行队列中的请求
- _Requirements: 3.5, 3.6_
- [x] 8.3 修改 request 方法处理 401 自动刷新
- 检测 401 响应触发刷新
- 刷新成功后重试原请求
- 刷新失败后跳转登录页
- _Requirements: 3.1, 3.3, 3.4_
- [x] 9. Final Checkpoint - 全部完成
- 确保所有测试通过ask the user if questions arise.
- 端到端测试:登录 → 等待过期 → 自动刷新 → 继续使用
## Notes
- Tasks marked with `*` are optional and can be skipped for faster MVP
- 后端改动需要先执行数据库迁移脚本
- 前端改动需要在后端接口完成后进行
- 建议先在测试环境验证,再部署到生产环境
- Access Token 有效期设置为 30 分钟,可根据需要调整
- Refresh Token 有效期设置为 7 天,可根据需要调整