# Implementation Plan: JWT Authentication System ## Overview 本实现计划将 JWT 权限认证体系集成到标注平台中。采用增量开发方式,先实现后端核心功能,再集成到现有 API,最后实现前端。每个任务都包含具体的实现步骤和测试要求。 ## Tasks - [x] 1. 环境准备和依赖安装 - 安装 PyJWT、bcrypt、python-multipart 等依赖包 - 更新 requirements.txt 文件 - 创建 .env.example 文件模板 - _Requirements: 9.1, 9.2, 9.3, 9.4_ - [ ] 2. 配置模块实现 - [x] 2.1 创建 config.py 配置文件 - 实现 Settings 类使用 pydantic-settings - 定义 JWT 相关配置(密钥、算法、过期时间) - 定义 OAuth 预留配置 - 添加默认值和环境变量读取 - _Requirements: 9.1, 9.2, 9.3, 9.4, 9.5, 13.5_ - [ ]* 2.2 编写配置模块单元测试 - 测试环境变量读取 - 测试默认值设置 - 测试配置验证 - _Requirements: 9.1, 9.2, 9.3, 9.4_ - [ ] 3. 数据库模型和初始化 - [x] 3.1 扩展 User 模型 - 在 models.py 中添加 User 类 - 定义所有必需字段(id, username, email, password_hash, role, oauth_provider, oauth_id, created_at) - 实现 from_row 类方法 - _Requirements: 8.1, 13.2_ - [x] 3.2 更新数据库初始化 - 在 database.py 的 init_database 函数中添加 users 表创建 SQL - 添加唯一约束(username, email) - 创建索引(username, email, oauth) - _Requirements: 8.1, 8.2, 8.3, 8.4, 8.5_ - [ ]* 3.3 编写数据库初始化测试 - 测试 users 表创建 - 测试唯一约束 - 测试索引创建 - _Requirements: 8.1, 8.2, 8.3, 8.4, 8.5_ - [ ] 4. Pydantic Schemas 定义 - [x] 4.1 创建 schemas/auth.py 文件 - 定义 UserRegister schema(username, email, password 验证) - 定义 UserLogin schema - 定义 TokenResponse schema - 定义 TokenRefresh schema - 定义 UserResponse schema - 定义 TokenPayload schema - _Requirements: 1.1, 1.4, 2.1, 3.1, 6.1_ - [ ]* 4.2 编写 schema 验证测试 - 测试密码长度验证(最少 8 字符) - 测试邮箱格式验证 - 测试用户名长度验证 - _Requirements: 1.4_ - [ ] 5. JWT Service 实现 - [x] 5.1 创建 services/jwt_service.py - 实现 create_access_token 方法(15分钟过期) - 实现 create_refresh_token 方法(7天过期) - 实现 verify_token 方法(验证签名和过期时间) - 处理 JWT 异常(ExpiredSignatureError, InvalidTokenError) - _Requirements: 2.1, 2.3, 2.4, 2.5, 3.1, 3.3, 4.6_ - [ ]* 5.2 编写 JWT Service 单元测试 - 测试 access token 创建和验证 - 测试 refresh token 创建和验证 - 测试 token 过期处理 - 测试无效 token 处理 - _Requirements: 2.4, 2.5, 3.2, 4.3, 4.4_ - [ ]* 5.3 编写 JWT Service 属性测试 - **Property 7: Token 过期时间正确设置** - **Validates: Requirements 2.4, 2.5** - [ ] 6. Auth Service 实现 - [x] 6.1 创建 services/auth_service.py - 实现 register_user 方法(用户注册) - 使用 bcrypt 哈希密码 - 检查用户名和邮箱唯一性 - 自动分配默认角色 "annotator" - _Requirements: 1.1, 1.2, 1.3, 1.5, 1.6, 7.1, 7.2_ - [x] 6.2 实现登录功能 - 实现 login_user 方法 - 验证用户名和密码 - 使用 bcrypt.checkpw 验证密码 - 生成 access_token 和 refresh_token - 返回 tokens 和用户信息 - _Requirements: 2.1, 2.2, 2.6, 7.4_ - [x] 6.3 实现 token 刷新功能 - 实现 refresh_tokens 方法 - 验证 refresh_token - 生成新的 access_token 和 refresh_token(token rotation) - 处理 token 过期和无效情况 - _Requirements: 3.1, 3.2, 3.4_ - [x] 6.4 实现用户查询功能 - 实现 get_current_user 方法 - 根据 user_id 查询用户信息 - 处理用户不存在情况 - _Requirements: 6.1, 6.3_ - [ ]* 6.5 编写 Auth Service 单元测试 - 测试用户注册成功场景 - 测试重复用户名/邮箱错误 - 测试登录成功和失败场景 - 测试 token 刷新 - 测试用户查询 - _Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 3.1, 3.2, 6.1_ - [ ]* 6.6 编写 Auth Service 属性测试 - **Property 1: 用户注册创建有效用户** - **Property 2: 密码哈希不可逆** - **Property 3: 短密码被拒绝** - **Property 4: 新用户默认角色** - **Property 5: 登录返回有效 Tokens** - **Property 6: Access Token 包含完整用户信息** - **Property 8: Token 刷新生成新令牌** - **Validates: Requirements 1.1, 1.2, 1.4, 1.5, 1.6, 2.1, 2.3, 3.1, 3.4** - [ ] 7. Checkpoint - 核心服务测试 - 确保所有核心服务测试通过 - 验证 JWT token 生成和验证正常 - 验证用户注册和登录流程 - 如有问题请询问用户 - [ ] 8. Auth Middleware 实现 - [x] 8.1 创建 middleware/auth_middleware.py - 实现 AuthMiddleware 类继承 BaseHTTPMiddleware - 定义公开路径列表(PUBLIC_PATHS) - 实现 dispatch 方法处理每个请求 - 从 Authorization header 提取 JWT token - 验证 token 格式(Bearer ) - 调用 JWTService.verify_token 验证 token - 将用户信息附加到 request.state.user - 处理各种错误情况(缺少 token、无效 token、过期 token) - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 5.1, 5.2, 5.3, 5.4, 5.5_ - [x] 8.2 实现角色检查装饰器 - 实现 require_role 装饰器函数 - 检查 request.state.user 中的角色 - 返回 403 错误如果角色不匹配 - _Requirements: 12.2, 12.3, 12.4, 12.5_ - [ ]* 8.3 编写 Middleware 单元测试 - 测试公开端点无需认证 - 测试受保护端点需要 token - 测试缺少 Authorization header - 测试无效 token 格式 - 测试过期 token - 测试用户信息附加到 request.state - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 5.1, 5.2, 5.3, 5.4, 5.5_ - [ ]* 8.4 编写 Middleware 属性测试 - **Property 9: 中间件验证有效 Token** - **Validates: Requirements 4.1, 4.5** - [ ] 9. Auth Router 实现 - [x] 9.1 创建 routers/auth.py - 创建 APIRouter 实例(prefix="/api/auth", tags=["authentication"]) - 实现 POST /register 端点 - 实现 POST /login 端点 - 实现 POST /refresh 端点 - 实现 GET /me 端点 - 添加详细的文档字符串 - 使用 Pydantic schemas 进行请求/响应验证 - _Requirements: 1.1, 2.1, 3.1, 6.1_ - [ ]* 9.2 编写 Auth Router 集成测试 - 测试注册端点(成功和失败场景) - 测试登录端点(成功和失败场景) - 测试 token 刷新端点 - 测试获取当前用户端点 - _Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 3.1, 3.2, 6.1, 6.2_ - [ ]* 9.3 编写 Auth Router 属性测试 - **Property 10: 用户信息端点返回正确数据** - **Validates: Requirements 6.1** - [ ] 10. 主应用集成 - [x] 10.1 更新 main.py - 导入 AuthMiddleware - 在 CORS 中间件之后添加 AuthMiddleware - 导入并注册 auth router - 确保中间件顺序正确 - _Requirements: 4.1, 11.1, 11.2, 11.3_ - [x] 10.2 更新 routers/__init__.py - 导出 auth router - _Requirements: 1.1, 2.1, 3.1, 6.1_ - [ ] 11. 现有 API 集成 - [x] 11.1 更新 Project Router - 在需要的端点中使用 request.state.user 获取当前用户 - 添加角色检查(如删除操作需要 admin 角色) - _Requirements: 11.1, 11.4, 12.2, 12.3_ - [x] 11.2 更新 Task Router - 在创建任务时使用 request.state.user.id 作为 assigned_to - 添加角色检查 - _Requirements: 11.2, 11.4, 12.2, 12.3_ - [x] 11.3 更新 Annotation Router - 在创建标注时使用 request.state.user.id 作为 user_id - 确保用户只能访问自己的标注 - _Requirements: 11.3, 11.4, 11.5, 12.2, 12.3_ - [ ]* 11.4 编写 API 集成测试 - **Property 11: 现有 API 端点受保护** - 测试所有受保护端点需要认证 - 测试用户信息正确传递到路由处理器 - **Validates: Requirements 11.1, 11.2, 11.3, 11.4** - [ ]* 11.5 编写角色权限属性测试 - **Property 12: 角色权限控制** - 测试不同角色的访问权限 - **Validates: Requirements 12.2, 12.3, 12.4** - [x] 12. Checkpoint - 后端完整测试 - 运行所有测试确保通过 - 测试完整的认证流程(注册 → 登录 → 访问受保护端点 → 刷新 token) - 验证中间件正确保护所有端点 - 验证角色权限控制 - 如有问题请询问用户 - [ ] 13. 环境配置和文档 - [x] 13.1 更新 .env.example - 添加 JWT_SECRET_KEY 示例 - 添加 JWT_ALGORITHM 示例 - 添加 ACCESS_TOKEN_EXPIRE_MINUTES 示例 - 添加 REFRESH_TOKEN_EXPIRE_DAYS 示例 - 添加 OAuth 预留配置示例 - _Requirements: 9.1, 9.2, 9.3, 9.4, 13.5_ - [x] 13.2 更新 backend/README.md - 添加认证系统说明 - 添加环境变量配置说明 - 添加 API 端点文档 - 添加使用示例 - _Requirements: 1.1, 2.1, 3.1, 6.1, 9.1_ - [ ] 14. 前端认证实现(可选) - [x] 14.1 创建认证 Atoms - 在 web/apps/lq_label/src/atoms/ 创建 auth-atoms.ts - 定义 authTokensAtom(使用 atomWithStorage) - 定义 currentUserAtom - 定义 isAuthenticatedAtom - 定义 logoutAtom - _Requirements: 2.1, 6.1_ - [x] 14.2 创建认证服务 - 在 web/apps/lq_label/src/services/ 创建 auth-service.ts - 实现 register 方法 - 实现 login 方法 - 实现 refreshToken 方法 - 实现 getCurrentUser 方法 - _Requirements: 1.1, 2.1, 3.1, 6.1_ - [x] 14.3 配置 Axios 拦截器 - 在 web/apps/lq_label/src/services/api.ts 更新 - 实现请求拦截器(自动附加 token) - 实现响应拦截器(处理 token 过期和自动刷新) - 实现请求队列机制 - _Requirements: 2.1, 3.1, 4.1, 4.4_ - [x] 14.4 创建登录组件 - 在 web/apps/lq_label/src/components/ 创建 login-form/ - 实现 LoginForm 组件 - 使用 Jotai 管理状态 - 调用 authService.login - 处理错误显示 - 登录成功后跳转 - _Requirements: 2.1_ - [x] 14.5 创建注册组件 - 在 web/apps/lq_label/src/components/ 创建 register-form/ - 实现 RegisterForm 组件 - 表单验证(密码长度、邮箱格式) - 调用 authService.register - 处理错误显示 - _Requirements: 1.1, 1.4_ - [x] 14.6 创建路由保护组件 - 在 web/apps/lq_label/src/components/ 创建 protected-route/ - 实现 ProtectedRoute 组件 - 检查 isAuthenticatedAtom - 未认证时重定向到登录页 - _Requirements: 4.1, 11.1, 11.2, 11.3_ - [x] 14.7 更新应用路由 - 在 web/apps/lq_label/src/app/app.tsx 中添加认证路由 - 添加 /login 路由 - 添加 /register 路由 - 使用 ProtectedRoute 包装受保护的路由 - _Requirements: 1.1, 2.1, 4.1_ - [ ] 14.8 更新现有 API 调用 - 将所有 axios 调用替换为 apiClient - 确保自动附加 token - 测试 token 刷新机制 - _Requirements: 4.1, 11.1, 11.2, 11.3_ - [ ] 15. 端到端测试 - [ ]* 15.1 编写完整认证流程测试 - 测试注册 → 登录 → 访问受保护端点 → 刷新 token → 登出 - 测试前后端集成 - 测试错误处理 - _Requirements: 1.1, 2.1, 3.1, 4.1, 6.1, 11.1, 11.2, 11.3_ - [ ] 16. Final Checkpoint - 完整系统验证 - 运行所有测试(单元测试 + 属性测试 + 集成测试) - 手动测试完整的用户流程 - 验证前后端集成 - 检查代码覆盖率(目标 80%+) - 确认所有需求已实现 - 如有问题请询问用户 ## Notes - 标记 `*` 的任务为可选测试任务,可以跳过以加快 MVP 开发 - 每个任务都引用了相关的需求编号,确保可追溯性 - Checkpoint 任务用于确保增量验证,及时发现问题 - 属性测试使用 Hypothesis 库,每个测试最少 100 次迭代 - 单元测试使用 pytest 框架 - 前端任务(Task 14)为可选,可以先完成后端再实现前端 - 所有测试文件必须保存在 `backend/test/` 目录中