# Pixel Game Server API接口文档 ## 概述 本文档描述了像素游戏服务器的完整API接口,包括用户认证、管理员后台、应用状态等功能。 **基础URL**: `http://localhost:3000` **API文档地址**: `http://localhost:3000/api-docs` **项目名称**: Pixel Game Server **版本**: 1.0.0 ## 通用响应格式 所有API接口都遵循统一的响应格式: ```json { "success": boolean, "data": object | null, "message": string, "error_code": string | null } ``` ### 字段说明 - `success`: 请求是否成功 - `data`: 响应数据(成功时返回) - `message`: 响应消息 - `error_code`: 错误代码(失败时返回) ## 接口分类 ### 1. 应用状态接口 (App) - `GET /` - 获取应用状态 ### 2. 用户认证接口 (Auth) - `POST /auth/login` - 用户登录 - `POST /auth/verification-code-login` - 验证码登录 - `POST /auth/send-login-verification-code` - 发送登录验证码 - `POST /auth/register` - 用户注册 - `POST /auth/github` - GitHub OAuth登录 - `POST /auth/forgot-password` - 发送密码重置验证码 - `POST /auth/reset-password` - 重置密码 - `PUT /auth/change-password` - 修改密码 - `POST /auth/send-email-verification` - 发送邮箱验证码 - `POST /auth/verify-email` - 验证邮箱验证码 - `POST /auth/resend-email-verification` - 重新发送邮箱验证码 - `POST /auth/debug-verification-code` - 调试验证码信息(开发环境) - `POST /auth/debug-clear-throttle` - 清除限流记录(开发环境) ### 3. 管理员接口 (Admin) - `POST /admin/auth/login` - 管理员登录 - `GET /admin/users` - 获取用户列表 - `GET /admin/users/:id` - 获取用户详情 - `POST /admin/users/:id/reset-password` - 重置用户密码 - `GET /admin/logs/runtime` - 获取运行日志 - `GET /admin/logs/archive` - 下载日志压缩包 ### 4. 用户管理接口 (User Management) - `PUT /admin/users/:id/status` - 修改用户状态 - `POST /admin/users/batch-status` - 批量修改用户状态 - `GET /admin/users/status-stats` - 获取用户状态统计 ## 接口列表 ### 应用状态接口 #### 1. 获取应用状态 **接口地址**: `GET /` **功能描述**: 返回应用的基本运行状态信息,用于健康检查和监控 #### 请求参数 无 #### 响应示例 **成功响应** (200): ```json { "service": "Pixel Game Server", "version": "1.0.0", "status": "running", "timestamp": "2025-12-23T10:00:00.000Z", "uptime": 3600, "environment": "development", "storage_mode": "memory" } ``` | 字段名 | 类型 | 说明 | |--------|------|------| | service | string | 服务名称 | | version | string | 服务版本 | | status | string | 运行状态 (running/starting/stopping/error) | | timestamp | string | 当前时间戳 | | uptime | number | 运行时间(秒) | | environment | string | 运行环境 (development/production/test) | | storage_mode | string | 存储模式 (database/memory) | ### 用户认证接口 #### 1. 用户登录 **接口地址**: `POST /auth/login` **功能描述**: 用户登录,支持用户名、邮箱或手机号登录 #### 请求参数 ```json { "identifier": "testuser", "password": "password123" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | identifier | string | 是 | 登录标识符,支持用户名、邮箱或手机号 | | password | string | 是 | 用户密码 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "user": { "id": "1", "username": "testuser", "nickname": "测试用户", "email": "test@example.com", "phone": "+8613800138000", "avatar_url": "https://example.com/avatar.jpg", "role": 1, "created_at": "2025-12-17T10:00:00.000Z" }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "is_new_user": false, "message": "登录成功" }, "message": "登录成功" } ``` **失败响应** (401): ```json { "success": false, "message": "用户名或密码错误", "error_code": "LOGIN_FAILED" } ``` #### 1.1 验证码登录 **接口地址**: `POST /auth/verification-code-login` **功能描述**: 使用邮箱或手机号和验证码进行登录,无需密码 #### 请求参数 ```json { "identifier": "test@example.com", "verification_code": "123456" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | identifier | string | 是 | 登录标识符(邮箱或手机号) | | verification_code | string | 是 | 6位数字验证码 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "user": { "id": "1", "username": "testuser", "nickname": "测试用户", "email": "test@example.com", "phone": "+8613800138000", "avatar_url": "https://example.com/avatar.jpg", "role": 1, "created_at": "2025-12-17T10:00:00.000Z" }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "is_new_user": false, "message": "验证码登录成功" }, "message": "验证码登录成功" } ``` **失败响应** (401): ```json { "success": false, "message": "验证码错误或已过期", "error_code": "VERIFICATION_CODE_LOGIN_FAILED" } ``` **可能的错误码**: - `VERIFICATION_CODE_LOGIN_FAILED`: 验证码错误或已过期 - `USER_NOT_FOUND`: 用户不存在 - `EMAIL_NOT_VERIFIED`: 邮箱未验证(邮箱登录时) - `INVALID_IDENTIFIER`: 无效的邮箱或手机号格式 #### 1.2 发送登录验证码 **接口地址**: `POST /auth/send-login-verification-code` **功能描述**: 向用户邮箱或手机发送登录验证码 #### 请求参数 ```json { "identifier": "test@example.com" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | identifier | string | 是 | 邮箱或手机号 | #### 响应示例 **成功响应** (200): ```json { "success": true, "message": "验证码发送成功", "data": { "sent_to": "test@example.com", "expires_in": 300 } } ``` **测试模式响应** (206): ```json { "success": false, "message": "测试模式:验证码已生成但未真实发送", "error_code": "TEST_MODE_ONLY", "data": { "verification_code": "123456", "sent_to": "test@example.com", "expires_in": 300, "is_test_mode": true } } ``` **失败响应** (404): ```json { "success": false, "message": "用户不存在", "error_code": "SEND_LOGIN_CODE_FAILED" } ``` #### 2. 用户注册 **接口地址**: `POST /auth/register` **功能描述**: 创建新用户账户 **重要说明**: - 如果提供邮箱,必须先调用发送验证码接口获取验证码 - 注册时会按以下顺序进行检查: 1. 首先检查用户名是否已存在 2. 检查邮箱是否已存在(如果提供) 3. 检查手机号是否已存在(如果提供) 4. 最后验证邮箱验证码(如果提供邮箱) - 这样确保验证码不会因为用户已存在而被无效消费 - 注册成功返回201,失败返回400 #### 请求参数 ```json { "username": "testuser", "password": "password123", "nickname": "测试用户", "email": "test@example.com", "email_verification_code": "123456" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | username | string | 是 | 用户名,只能包含字母、数字和下划线,长度1-50字符 | | password | string | 是 | 密码,必须包含字母和数字,长度8-128字符 | | nickname | string | 是 | 用户昵称,长度1-50字符 | | email | string | 否 | 邮箱地址(如果提供,必须先获取验证码) | | phone | string | 否 | 手机号码 | | email_verification_code | string | 条件必填 | 邮箱验证码,提供邮箱时必填 | #### 响应示例 **成功响应** (201): ```json { "success": true, "data": { "user": { "id": "2", "username": "testuser", "nickname": "测试用户", "email": "test@example.com", "phone": "+8613800138000", "avatar_url": null, "role": 1, "created_at": "2025-12-17T10:00:00.000Z" }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "is_new_user": true, "message": "注册成功" }, "message": "注册成功" } ``` **失败响应** (400): **用户名已存在**: ```json { "success": false, "message": "用户名已存在", "error_code": "REGISTER_FAILED" } ``` **邮箱已存在**: ```json { "success": false, "message": "邮箱已存在", "error_code": "REGISTER_FAILED" } ``` **手机号已存在**: ```json { "success": false, "message": "手机号已存在", "error_code": "REGISTER_FAILED" } ``` **邮箱验证码相关错误**: ```json { "success": false, "message": "提供邮箱时必须提供邮箱验证码", "error_code": "REGISTER_FAILED" } ``` **频率限制响应** (429): ```json { "success": false, "message": "注册请求过于频繁,请5分钟后再试", "error_code": "TOO_MANY_REQUESTS", "throttle_info": { "limit": 10, "window_seconds": 300, "current_requests": 10, "reset_time": "2025-12-24T11:26:41.136Z" } } ``` #### 3. GitHub OAuth登录 **接口地址**: `POST /auth/github` **功能描述**: 使用GitHub账户登录或注册 #### 请求参数 ```json { "github_id": "12345678", "username": "octocat", "nickname": "The Octocat", "email": "octocat@github.com", "avatar_url": "https://github.com/images/error/octocat_happy.gif" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | github_id | string | 是 | GitHub用户ID | | username | string | 是 | GitHub用户名 | | nickname | string | 是 | GitHub显示名称 | | email | string | 否 | GitHub邮箱地址 | | avatar_url | string | 否 | GitHub头像URL | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "user": { "id": "3", "username": "octocat", "nickname": "The Octocat", "email": "octocat@github.com", "phone": null, "avatar_url": "https://github.com/images/error/octocat_happy.gif", "role": 1, "created_at": "2025-12-17T10:00:00.000Z" }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "is_new_user": true, "message": "GitHub账户绑定成功" }, "message": "GitHub账户绑定成功" } ``` #### 4. 发送密码重置验证码 **接口地址**: `POST /auth/forgot-password` **功能描述**: 向用户邮箱或手机发送密码重置验证码 #### 请求参数 ```json { "identifier": "test@example.com" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | identifier | string | 是 | 邮箱或手机号 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "verification_code": "123456" }, "message": "验证码已发送,请查收" } ``` **注意**: 实际应用中不应返回验证码,这里仅用于演示。 #### 5. 重置密码 **接口地址**: `POST /auth/reset-password` **功能描述**: 使用验证码重置用户密码 #### 请求参数 ```json { "identifier": "test@example.com", "verification_code": "123456", "new_password": "newpassword123" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | identifier | string | 是 | 邮箱或手机号 | | verification_code | string | 是 | 6位数字验证码 | | new_password | string | 是 | 新密码,必须包含字母和数字,长度8-128字符 | #### 响应示例 **成功响应** (200): ```json { "success": true, "message": "密码重置成功" } ``` #### 6. 修改密码 **接口地址**: `PUT /auth/change-password` **功能描述**: 用户修改自己的密码(需要提供旧密码) #### 请求参数 ```json { "user_id": "1", "old_password": "oldpassword123", "new_password": "newpassword123" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | user_id | string | 是 | 用户ID(实际应用中应从JWT令牌中获取) | | old_password | string | 是 | 当前密码 | | new_password | string | 是 | 新密码,必须包含字母和数字,长度8-128字符 | #### 响应示例 **成功响应** (200): ```json { "success": true, "message": "密码修改成功" } ``` #### 7. 发送邮箱验证码 **接口地址**: `POST /auth/send-email-verification` **功能描述**: 向指定邮箱发送验证码,用于注册时的邮箱验证 #### 请求参数 ```json { "email": "test@example.com" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | email | string | 是 | 邮箱地址 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "verification_code": "123456", "is_test_mode": false }, "message": "验证码已发送,请查收" } ``` **测试模式响应** (206): ```json { "success": false, "data": { "verification_code": "059174", "is_test_mode": true }, "message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。", "error_code": "TEST_MODE_ONLY" } ``` #### 8. 验证邮箱验证码 **接口地址**: `POST /auth/verify-email` **功能描述**: 使用验证码验证邮箱 #### 请求参数 ```json { "email": "test@example.com", "verification_code": "123456" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | email | string | 是 | 邮箱地址 | | verification_code | string | 是 | 6位数字验证码 | #### 响应示例 **成功响应** (200): ```json { "success": true, "message": "邮箱验证成功" } ``` #### 9. 重新发送邮箱验证码 **接口地址**: `POST /auth/resend-email-verification` **功能描述**: 重新向指定邮箱发送验证码 #### 请求参数 ```json { "email": "test@example.com" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | email | string | 是 | 邮箱地址 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "verification_code": "123456", "is_test_mode": false }, "message": "验证码已重新发送,请查收" } ``` #### 10. 调试验证码信息 **接口地址**: `POST /auth/debug-verification-code` **功能描述**: 获取验证码的详细调试信息(仅开发环境使用) #### 请求参数 ```json { "email": "test@example.com" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | email | string | 是 | 邮箱地址 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "email": "test@example.com", "verification_code": "123456", "expires_at": "2025-12-23T10:15:00.000Z", "created_at": "2025-12-23T10:00:00.000Z" }, "message": "调试信息获取成功" } ``` #### 11. 清除限流记录 **接口地址**: `POST /auth/debug-clear-throttle` **功能描述**: 清除所有限流记录(仅开发环境使用) **注意**: 此接口用于开发测试,清除所有IP的频率限制记录 #### 请求参数 无 #### 响应示例 **成功响应** (200): ```json { "success": true, "message": "限流记录已清除" } ``` ### 管理员接口 **注意**:所有管理员接口都需要在 Header 中携带 `Authorization: Bearer `,且用户角色必须为管理员 (role=9)。 #### 1. 管理员登录 **接口地址**: `POST /admin/auth/login` **功能描述**: 管理员登录,仅允许 role=9 的账户登录后台 #### 请求参数 ```json { "identifier": "admin", "password": "Admin123456" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | identifier | string | 是 | 登录标识符(用户名/邮箱/手机号) | | password | string | 是 | 密码 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "admin": { "id": "1", "username": "admin", "nickname": "管理员", "role": 9 }, "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_at": 1766102400000 }, "message": "管理员登录成功" } ``` #### 2. 获取用户列表 **接口地址**: `GET /admin/users` **功能描述**: 分页获取所有注册用户列表 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | limit | number | 否 | 每页数量,默认100 | | offset | number | 否 | 偏移量,默认0 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "users": [ { "id": "1", "username": "user1", "nickname": "小明", "email": "user1@example.com", "email_verified": false, "phone": "+8613800138000", "avatar_url": "https://example.com/avatar.png", "role": 1, "created_at": "2025-12-19T00:00:00.000Z", "updated_at": "2025-12-19T00:00:00.000Z" } ], "limit": 100, "offset": 0 }, "message": "用户列表获取成功" } ``` #### 3. 获取用户详情 **接口地址**: `GET /admin/users/:id` **功能描述**: 获取指定用户的详细信息 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | string | 是 | 用户ID(路径参数) | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "user": { "id": "1", "username": "user1", "nickname": "小明", "email": "user1@example.com", "email_verified": false, "phone": "+8613800138000", "avatar_url": "https://example.com/avatar.png", "role": 1, "created_at": "2025-12-19T00:00:00.000Z", "updated_at": "2025-12-19T00:00:00.000Z" } }, "message": "用户信息获取成功" } ``` #### 4. 重置用户密码 **接口地址**: `POST /admin/users/:id/reset-password` **功能描述**: 管理员强制重置指定用户的密码 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | string | 是 | 用户ID(路径参数) | | new_password | string | 是 | 新密码(至少8位,包含字母和数字) | ```json { "new_password": "NewPass1234" } ``` #### 响应示例 **成功响应** (200): ```json { "success": true, "message": "密码重置成功" } ``` #### 5. 获取运行日志 **接口地址**: `GET /admin/logs/runtime` **功能描述**: 从 logs/ 目录读取最近的日志行 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | lines | number | 否 | 返回行数,默认200,最大2000 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "file": "dev.log", "updated_at": "2025-12-19T19:10:15.000Z", "lines": [ "[2025-12-19 19:10:15] INFO: Server started", "[2025-12-19 19:10:16] INFO: Database connected" ] }, "message": "运行日志获取成功" } ``` #### 6. 下载日志压缩包 **接口地址**: `GET /admin/logs/archive` **功能描述**: 将 logs/ 目录打包为 tar.gz 并下载 #### 请求参数 无 #### 响应示例 **成功响应** (200): - Content-Type: `application/gzip` - Content-Disposition: `attachment; filename="logs-2025-12-23T10-00-00-000Z.tar.gz"` - 返回二进制流(tar.gz 文件) ### 用户管理接口 **注意**:所有用户管理接口都需要管理员权限,需要在 Header 中携带 `Authorization: Bearer `。 #### 1. 修改用户状态 **接口地址**: `PUT /admin/users/:id/status` **功能描述**: 管理员修改指定用户的账户状态,支持激活、锁定、禁用等操作 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | string | 是 | 用户ID(路径参数) | | status | string | 是 | 用户状态枚举值 | | reason | string | 否 | 修改原因 | ```json { "status": "locked", "reason": "用户违反社区规定" } ``` **用户状态枚举值:** - `active` - 正常状态,可以正常使用 - `inactive` - 未激活,需要邮箱验证 - `locked` - 已锁定,临时禁用 - `banned` - 已禁用,管理员操作 - `deleted` - 已删除,软删除状态 - `pending` - 待审核,需要管理员审核 #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "user": { "id": "1", "username": "testuser", "nickname": "测试用户", "status": "locked", "status_description": "已锁定", "updated_at": "2025-12-24T10:00:00.000Z" }, "reason": "用户违反社区规定" }, "message": "用户状态修改成功" } ``` #### 2. 批量修改用户状态 **接口地址**: `POST /admin/users/batch-status` **功能描述**: 管理员批量修改多个用户的账户状态 #### 请求参数 ```json { "user_ids": ["1", "2", "3"], "status": "locked", "reason": "批量处理违规用户" } ``` | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | user_ids | array | 是 | 用户ID列表(1-100个) | | status | string | 是 | 用户状态枚举值 | | reason | string | 否 | 批量修改原因 | #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "result": { "success_users": [ { "id": "1", "username": "user1", "nickname": "用户1", "status": "locked", "status_description": "已锁定", "updated_at": "2025-12-24T10:00:00.000Z" } ], "failed_users": [ { "user_id": "999", "error": "用户不存在" } ], "success_count": 1, "failed_count": 1, "total_count": 2 }, "reason": "批量处理违规用户" }, "message": "批量用户状态修改完成,成功:1,失败:1" } ``` #### 3. 获取用户状态统计 **接口地址**: `GET /admin/users/status-stats` **功能描述**: 获取各种用户状态的数量统计信息 #### 请求参数 无 #### 响应示例 **成功响应** (200): ```json { "success": true, "data": { "stats": { "active": 1250, "inactive": 45, "locked": 12, "banned": 8, "deleted": 3, "pending": 15, "total": 1333 }, "timestamp": "2025-12-24T10:00:00.000Z" }, "message": "用户状态统计获取成功" } ## 测试指南和边界条件 ### 🧪 **前端测试建议** 为了确保前端应用的稳定性,建议对以下场景进行全面测试: #### **1. 用户认证测试** ##### **注册功能测试** ```javascript // 正常注册流程 const testNormalRegister = async () => { // 1. 发送邮箱验证码 const codeResponse = await sendEmailVerification('test@example.com'); // 2. 使用验证码注册 const registerResponse = await register({ username: 'testuser123', password: 'Test123456', nickname: '测试用户', email: 'test@example.com', email_verification_code: codeResponse.data.verification_code }); expect(registerResponse.success).toBe(true); expect(registerResponse.data.user.username).toBe('testuser123'); expect(registerResponse.data.access_token).toBeDefined(); }; // 边界条件测试 const testRegisterEdgeCases = async () => { // 密码强度测试 await expectError(register({ username: 'test', password: '123', // 太短 nickname: '测试' }), 'REGISTER_FAILED'); // 用户名重复测试 await expectError(register({ username: 'existinguser', // 已存在 password: 'Test123456', nickname: '测试' }), 'REGISTER_FAILED'); // 邮箱验证码错误测试 await expectError(register({ username: 'newuser', password: 'Test123456', nickname: '测试', email: 'test@example.com', email_verification_code: '000000' // 错误验证码 }), 'REGISTER_FAILED'); }; ``` ##### **登录功能测试** ```javascript // 多种登录方式测试 const testLoginMethods = async () => { // 用户名登录 await testLogin('testuser', 'password123'); // 邮箱登录 await testLogin('test@example.com', 'password123'); // 手机号登录(如果支持) await testLogin('+8613800138000', 'password123'); }; // 登录失败场景测试 const testLoginFailures = async () => { // 用户不存在 await expectError(login('nonexistent', 'password'), 'LOGIN_FAILED'); // 密码错误 await expectError(login('testuser', 'wrongpassword'), 'LOGIN_FAILED'); // 账户被锁定 await expectError(login('lockeduser', 'password'), 'LOGIN_FAILED'); }; ``` #### **2. 验证码功能测试** ##### **验证码生成和验证** ```javascript // 验证码频率限制测试 const testVerificationRateLimit = async () => { const email = 'test@example.com'; // 第一次发送 - 应该成功 const response1 = await sendEmailVerification(email); expect(response1.success).toBe(true); // 立即再次发送 - 应该被限制 await expectError( sendEmailVerification(email), 'TOO_MANY_REQUESTS', 429 ); // 等待冷却时间后再次发送 await sleep(60000); // 等待1分钟 const response2 = await sendEmailVerification(email); expect(response2.success).toBe(true); }; // 验证码尝试次数限制测试 const testVerificationAttempts = async () => { const email = 'test@example.com'; const response = await sendEmailVerification(email); const correctCode = response.data.verification_code; // 错误尝试3次 for (let i = 0; i < 3; i++) { await expectError( verifyEmail(email, '000000'), 'VERIFICATION_FAILED' ); } // 第4次尝试,即使验证码正确也应该失败 await expectError( verifyEmail(email, correctCode), 'VERIFICATION_FAILED' ); }; ``` #### **3. 管理员功能测试** ##### **权限验证测试** ```javascript // 管理员登录测试 const testAdminLogin = async () => { // 正确的管理员凭据 const response = await adminLogin('admin', 'Admin123456'); expect(response.success).toBe(true); expect(response.data.admin.role).toBe(9); // 普通用户尝试管理员登录 await expectError( adminLogin('normaluser', 'password'), 'ADMIN_LOGIN_FAILED', 403 ); }; // 管理员操作权限测试 const testAdminOperations = async () => { const adminToken = await getAdminToken(); // 有效token的操作 const users = await getUserList(adminToken); expect(users.success).toBe(true); // 无效token的操作 await expectError( getUserList('invalid_token'), 'UNAUTHORIZED', 401 ); // 普通用户token的操作 const userToken = await getUserToken(); await expectError( getUserList(userToken), 'FORBIDDEN', 403 ); }; ``` #### **4. 用户状态管理测试** ##### **状态变更测试** ```javascript // 用户状态修改测试 const testUserStatusUpdate = async () => { const adminToken = await getAdminToken(); const userId = '1'; // 锁定用户 const lockResponse = await updateUserStatus(adminToken, userId, { status: 'locked', reason: '违反社区规定' }); expect(lockResponse.success).toBe(true); expect(lockResponse.data.user.status).toBe('locked'); // 被锁定用户尝试登录 await expectError( login('lockeduser', 'password'), 'LOGIN_FAILED', 403 ); // 恢复用户状态 await updateUserStatus(adminToken, userId, { status: 'active', reason: '恢复正常' }); }; // 批量状态修改测试 const testBatchStatusUpdate = async () => { const adminToken = await getAdminToken(); const response = await batchUpdateUserStatus(adminToken, { user_ids: ['1', '2', '999'], // 包含不存在的用户ID status: 'locked', reason: '批量处理' }); expect(response.success).toBe(true); expect(response.data.result.success_count).toBe(2); expect(response.data.result.failed_count).toBe(1); expect(response.data.result.failed_users[0].user_id).toBe('999'); }; ``` #### **5. 安全功能测试** ##### **频率限制测试** ```javascript // 登录频率限制测试 const testLoginRateLimit = async () => { // 快速连续登录尝试 for (let i = 0; i < 3; i++) { try { await login('testuser', 'wrongpassword'); } catch (error) { if (error.status === 429) { expect(error.message).toContain('Too Many Requests'); break; } } } }; // 维护模式测试 const testMaintenanceMode = async () => { // 模拟维护模式开启 // 所有请求都应该返回503 await expectError( getAppStatus(), 'SERVICE_UNAVAILABLE', 503 ); }; ``` #### **6. 错误处理测试** ##### **网络错误处理** ```javascript // 超时处理测试 const testTimeout = async () => { // 模拟长时间操作 await expectError( slowOperation(), 'REQUEST_TIMEOUT', 408 ); }; // 内容类型验证测试 const testContentType = async () => { // 错误的Content-Type await expectError( fetch('/auth/login', { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: 'invalid data' }), 'UNSUPPORTED_MEDIA_TYPE', 415 ); }; ``` ### 📋 **测试检查清单** #### **功能测试** - [ ] 用户注册(正常流程) - [ ] 用户注册(邮箱验证流程) - [ ] 用户登录(用户名/邮箱/手机号) - [ ] GitHub OAuth登录 - [ ] 密码重置流程 - [ ] 密码修改功能 - [ ] 邮箱验证码发送和验证 - [ ] 管理员登录 - [ ] 用户列表查询 - [ ] 用户详情查询 - [ ] 用户密码重置(管理员) - [ ] 用户状态管理 - [ ] 批量用户状态修改 - [ ] 用户状态统计 - [ ] 运行日志查询 - [ ] 日志文件下载 #### **边界条件测试** - [ ] 密码强度验证(太短、太简单) - [ ] 用户名格式验证(特殊字符、长度) - [ ] 邮箱格式验证 - [ ] 验证码格式验证(非6位数字) - [ ] 用户名重复检查 - [ ] 邮箱重复检查 - [ ] 不存在用户的操作 - [ ] 无效验证码验证 - [ ] 过期验证码验证 - [ ] 验证码尝试次数限制 #### **安全测试** - [ ] 频率限制(登录、发送验证码) - [ ] 权限验证(管理员接口) - [ ] Token有效性验证 - [ ] 用户状态检查(锁定、禁用用户登录) - [ ] 维护模式功能 - [ ] 内容类型验证 - [ ] 请求超时处理 #### **错误处理测试** - [ ] 网络连接错误 - [ ] 服务器内部错误(500) - [ ] 请求超时(408) - [ ] 频率限制(429) - [ ] 权限不足(403) - [ ] 资源不存在(404) - [ ] 参数验证错误(400) - [ ] 维护模式(503) ### 🔧 **测试工具推荐** #### **API测试工具** - **Postman**: 手动API测试和文档 - **Insomnia**: 轻量级API客户端 - **curl**: 命令行测试 - **HTTPie**: 用户友好的命令行工具 #### **自动化测试框架** - **Jest**: JavaScript测试框架 - **Cypress**: 端到端测试 - **Playwright**: 现代Web测试 - **Supertest**: Node.js HTTP测试 #### **测试脚本示例** 项目提供了现成的测试脚本: - `test-api.ps1` - Windows PowerShell测试脚本 - `test-api.sh` - Linux/macOS Bash测试脚本 运行测试脚本: ```bash # Windows .\test-api.ps1 # Linux/macOS ./test-api.sh # 自定义参数 .\test-api.ps1 -BaseUrl "http://localhost:3000" -TestEmail "custom@example.com" ``` ### 📊 **测试数据管理** #### **测试环境配置** - **内存模式**: 数据重启后清空,适合快速测试 - **数据库模式**: 数据持久化,适合完整功能测试 - **测试模式**: 邮件不真实发送,验证码在响应中返回 #### **测试数据清理** ```javascript // 清理测试数据 const cleanupTestData = async () => { // 删除测试用户 await deleteTestUsers(); // 清理Redis验证码 await clearVerificationCodes(); // 重置计数器 await resetRateLimitCounters(); }; ``` ### ⚠️ **测试注意事项** 1. **频率限制**: 测试时注意API频率限制,避免被限制 2. **测试隔离**: 每个测试用例使用独立的测试数据 3. **异步操作**: 注意验证码生成和验证的时序 4. **错误恢复**: 测试失败后要清理测试数据 5. **环境差异**: 开发、测试、生产环境的配置差异 6. **数据一致性**: 并发测试时注意数据竞争条件 ### 🚀 **性能测试建议** #### **负载测试场景** - 并发用户注册 - 高频验证码发送 - 大量用户同时登录 - 管理员批量操作 - 日志文件下载 #### **性能指标** - 响应时间 < 2秒(正常操作) - 吞吐量 > 100 req/s - 错误率 < 1% - 内存使用稳定 - CPU使用率 < 80% ### **通用错误代码** | 错误代码 | HTTP状态码 | 说明 | 触发条件 | |----------|------------|------|----------| | LOGIN_FAILED | 401 | 登录失败 | 用户名不存在、密码错误、账户被锁定 | | REGISTER_FAILED | 400/409 | 注册失败 | 用户名已存在、密码强度不足、验证码错误 | | GITHUB_OAUTH_FAILED | 401 | GitHub OAuth失败 | GitHub认证信息无效 | | SEND_CODE_FAILED | 400 | 发送验证码失败 | 邮箱格式错误、发送服务异常 | | RESET_PASSWORD_FAILED | 400 | 重置密码失败 | 验证码无效、密码强度不足 | | CHANGE_PASSWORD_FAILED | 400 | 修改密码失败 | 旧密码错误、新密码强度不足 | | TEST_MODE_ONLY | 206 | 测试模式 | 邮件服务未配置,验证码未真实发送 | ### **管理员相关错误代码** | 错误代码 | HTTP状态码 | 说明 | 触发条件 | |----------|------------|------|----------| | ADMIN_LOGIN_FAILED | 401/403 | 管理员登录失败 | 非管理员用户、凭据错误 | | ADMIN_USERS_FAILED | 500 | 获取用户列表失败 | 数据库查询异常 | | ADMIN_OPERATION_FAILED | 400/500 | 管理员操作失败 | 参数错误、系统异常 | ### **用户状态相关错误代码** | 错误代码 | HTTP状态码 | 说明 | 触发条件 | |----------|------------|------|----------| | USER_STATUS_UPDATE_FAILED | 400/404 | 用户状态修改失败 | 用户不存在、状态值无效 | | BATCH_USER_STATUS_UPDATE_FAILED | 400 | 批量用户状态修改失败 | 用户ID列表为空、状态值无效 | | USER_STATUS_STATS_FAILED | 500 | 用户状态统计失败 | 数据库查询异常 | ### **安全相关错误代码** | 错误代码 | HTTP状态码 | 说明 | 触发条件 | |----------|------------|------|----------| | SERVICE_UNAVAILABLE | 503 | 系统维护中 | 维护模式开启 | | TOO_MANY_REQUESTS | 429 | 请求过于频繁 | 触发频率限制 | | REQUEST_TIMEOUT | 408 | 请求超时 | 操作执行时间过长 | | UNSUPPORTED_MEDIA_TYPE | 415 | 不支持的媒体类型 | Content-Type不正确 | | UNAUTHORIZED | 401 | 未授权 | Token无效或过期 | | FORBIDDEN | 403 | 权限不足 | 非管理员访问管理员接口 | ### **验证码相关错误代码** | 错误代码 | HTTP状态码 | 说明 | 触发条件 | |----------|------------|------|----------| | VERIFICATION_CODE_EXPIRED | 400 | 验证码已过期 | 验证码超过有效期(5分钟) | | VERIFICATION_CODE_INVALID | 400 | 验证码无效 | 验证码格式错误或不存在 | | VERIFICATION_CODE_LOGIN_FAILED | 401 | 验证码登录失败 | 验证码错误、已过期或用户邮箱未验证 | | SEND_LOGIN_CODE_FAILED | 400/404 | 发送登录验证码失败 | 用户不存在或发送服务异常 | | VERIFICATION_CODE_ATTEMPTS_EXCEEDED | 400 | 验证码尝试次数过多 | 错误尝试超过3次 | | VERIFICATION_CODE_RATE_LIMITED | 429 | 验证码发送频率限制 | 1分钟内重复发送 | | VERIFICATION_CODE_HOURLY_LIMIT | 429 | 验证码每小时限制 | 1小时内发送超过5次 | ### **详细错误响应格式** #### **标准错误响应** ```json { "success": false, "message": "具体错误描述", "error_code": "ERROR_CODE", "timestamp": "2025-12-24T10:00:00.000Z" } ``` #### **验证错误响应** ```json { "success": false, "message": "参数验证失败", "error_code": "VALIDATION_FAILED", "errors": [ { "field": "password", "message": "密码长度至少8位" }, { "field": "email", "message": "邮箱格式不正确" } ] } ``` #### **频率限制错误响应** ```json { "success": false, "message": "请求过于频繁,请稍后再试", "error_code": "TOO_MANY_REQUESTS", "retry_after": 60, "limit_info": { "limit": 5, "remaining": 0, "reset_time": "2025-12-24T10:01:00.000Z" } } ``` #### **维护模式错误响应** ```json { "success": false, "message": "系统正在维护中,请稍后再试", "error_code": "SERVICE_UNAVAILABLE", "maintenance_info": { "start_time": "2025-12-24T10:00:00.000Z", "estimated_end_time": "2025-12-24T12:00:00.000Z", "retry_after": 1800, "reason": "系统升级维护" } } ``` ## 数据验证规则 ### 用户名规则 - 长度:1-50字符 - 格式:只能包含字母、数字和下划线 - 正则表达式:`^[a-zA-Z0-9_]+$` ### 密码规则 - 长度:8-128字符 - 格式:必须包含字母和数字 - 正则表达式:`^(?=.*[a-zA-Z])(?=.*\d)` ### 验证码规则 - 长度:6位数字 - 正则表达式:`^\d{6}$` - 有效期:通常为5-15分钟 ### 邮箱规则 - 格式:符合标准邮箱格式 - 验证:支持邮箱验证码验证 ### 管理员权限 - 角色:role=9 为管理员 - 认证:需要 JWT Token - 权限:可管理所有用户数据 ## 使用示例 ### JavaScript/TypeScript 示例 ```typescript // 获取应用状态 const statusResponse = await fetch('http://localhost:3000/'); const statusData = await statusResponse.json(); console.log('服务状态:', statusData.status); // 用户登录 const loginResponse = await fetch('http://localhost:3000/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ identifier: 'testuser', password: 'password123' }) }); const loginData = await loginResponse.json(); if (loginData.success) { const token = loginData.data.access_token; // 保存token用于后续请求 localStorage.setItem('token', token); } // 用户注册(带邮箱验证) // 1. 先发送邮箱验证码 const sendCodeResponse = await fetch('http://localhost:3000/auth/send-email-verification', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: 'newuser@example.com' }) }); // 2. 用户输入验证码后进行注册 const registerResponse = await fetch('http://localhost:3000/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username: 'newuser', password: 'password123', nickname: '新用户', email: 'newuser@example.com', email_verification_code: '123456' }) }); // 管理员登录 const adminLoginResponse = await fetch('http://localhost:3000/admin/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ identifier: 'admin', password: 'Admin123456' }) }); const adminData = await adminLoginResponse.json(); if (adminData.success) { const adminToken = adminData.data.access_token; // 获取用户列表 const usersResponse = await fetch('http://localhost:3000/admin/users?limit=10&offset=0', { headers: { 'Authorization': `Bearer ${adminToken}` } }); const usersData = await usersResponse.json(); console.log('用户列表:', usersData.data.users); } ``` ### cURL 示例 ```bash # 获取应用状态 curl -X GET http://localhost:3000/ # 用户登录 curl -X POST http://localhost:3000/auth/login \ -H "Content-Type: application/json" \ -d '{ "identifier": "testuser", "password": "password123" }' # 发送登录验证码 curl -X POST http://localhost:3000/auth/send-login-verification-code \ -H "Content-Type: application/json" \ -d '{ "identifier": "test@example.com" }' # 验证码登录 curl -X POST http://localhost:3000/auth/verification-code-login \ -H "Content-Type: application/json" \ -d '{ "identifier": "test@example.com", "verification_code": "123456" }' # 发送邮箱验证码 curl -X POST http://localhost:3000/auth/send-email-verification \ -H "Content-Type: application/json" \ -d '{ "email": "newuser@example.com" }' # 用户注册 curl -X POST http://localhost:3000/auth/register \ -H "Content-Type: application/json" \ -d '{ "username": "newuser", "password": "password123", "nickname": "新用户", "email": "newuser@example.com", "email_verification_code": "123456" }' # 管理员登录 curl -X POST http://localhost:3000/admin/auth/login \ -H "Content-Type: application/json" \ -d '{ "identifier": "admin", "password": "Admin123456" }' # 获取用户列表(需要管理员Token) curl -X GET "http://localhost:3000/admin/users?limit=10&offset=0" \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" # 重置用户密码 curl -X POST http://localhost:3000/admin/users/1/reset-password \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -d '{ "new_password": "NewPass1234" }' # 获取运行日志 curl -X GET "http://localhost:3000/admin/logs/runtime?lines=100" \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" # 下载日志压缩包 curl -X GET http://localhost:3000/admin/logs/archive \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -o logs.tar.gz ``` ## 安全特性 ### 1. 频率限制 (Rate Limiting) 系统实现了基于IP地址的频率限制,防止恶意攻击和滥用: #### 限制策略 | 接口类型 | 限制规则 | 时间窗口 | 说明 | |----------|----------|----------|------| | 登录接口 | 5次/分钟 | 60秒 | 防止暴力破解 | | 注册接口 | 10次/5分钟 | 300秒 | 防止批量注册(开发环境已放宽) | | 发送验证码 | 1次/分钟 | 60秒 | 防止验证码滥发 | | 密码重置 | 3次/小时 | 3600秒 | 限制密码重置频率 | | 管理员操作 | 10次/分钟 | 60秒 | 限制管理员操作频率 | | 一般接口 | 30次/分钟 | 60秒 | 通用API限制 | 100次/分钟 | 60秒 | 防止接口滥用 | #### 响应示例 当触发频率限制时,返回 **429 Too Many Requests**: ```json { "success": false, "message": "注册请求过于频繁,请5分钟后再试", "error_code": "TOO_MANY_REQUESTS", "throttle_info": { "limit": 10, "window_seconds": 300, "current_requests": 10, "reset_time": "2025-12-24T11:26:41.136Z" } } ``` **重要说明**: - 频率限制基于IP地址 - 超过限制后需要等待到重置时间才能再次请求 - 开发环境下注册接口限制已放宽至10次/5分钟 ### 2. 维护模式 (Maintenance Mode) 系统支持维护模式,在系统升级或维护期间暂停服务: #### 启用方式 设置环境变量: ```bash MAINTENANCE_MODE=true MAINTENANCE_START_TIME=2025-12-24T10:00:00.000Z MAINTENANCE_END_TIME=2025-12-24T12:00:00.000Z MAINTENANCE_REASON=系统升级维护 MAINTENANCE_RETRY_AFTER=1800 ``` #### 响应示例 维护模式下所有请求返回 **503 Service Unavailable**: ```json { "success": false, "message": "系统正在维护中,请稍后再试", "error_code": "SERVICE_UNAVAILABLE", "maintenance_info": { "start_time": "2025-12-24T10:00:00.000Z", "estimated_end_time": "2025-12-24T12:00:00.000Z", "retry_after": 1800, "reason": "系统升级维护" } } ``` ### 3. 内容类型验证 (Content Type Validation) 系统验证POST/PUT请求的Content-Type头: #### 支持的内容类型 - `application/json` - JSON数据 - `application/x-www-form-urlencoded` - 表单数据 - `multipart/form-data` - 文件上传 #### 响应示例 不支持的内容类型返回 **415 Unsupported Media Type**: ```json { "statusCode": 415, "message": "不支持的媒体类型", "error": "Unsupported Media Type" } ``` ### 4. 请求超时控制 (Request Timeout) 系统为不同类型的操作设置了超时限制: #### 超时配置 | 操作类型 | 超时时间 | 说明 | |----------|----------|------| | 普通操作 | 30秒 | 一般API请求 | | 数据库查询 | 60秒 | 复杂查询操作 | | 慢操作 | 120秒 | 批量处理等耗时操作 | #### 响应示例 请求超时返回 **408 Request Timeout**: ```json { "statusCode": 408, "message": "请求超时", "error": "Request Timeout" } ``` ### 5. 用户状态管理 (User Status Management) 系统支持细粒度的用户状态控制: #### 用户状态枚举 | 状态值 | 状态名称 | 说明 | |--------|----------|------| | active | 正常 | 用户可以正常使用所有功能 | | inactive | 未激活 | 新注册用户,需要邮箱验证 | | locked | 锁定 | 临时锁定,可以解锁 | | banned | 禁用 | 永久禁用,需要管理员处理 | | deleted | 删除 | 软删除状态,数据保留 | | pending | 待审核 | 需要管理员审核激活 | #### 状态检查 登录时系统会检查用户状态: - `active`: 正常登录 - `inactive`: 提示需要邮箱验证 - `locked`: 返回账户锁定错误 - `banned`: 返回账户禁用错误 - `deleted`: 返回账户不存在错误 - `pending`: 返回账户待审核错误 ### 6. 安全最佳实践 #### JWT Token 安全 - Token 有效期:8小时 - 使用 HS256 算法签名 - 包含用户ID、角色等关键信息 - 建议在客户端安全存储 #### 密码安全 - 使用 bcrypt 加密存储 - 支持密码强度验证 - 不在日志中记录明文密码 - 支持密码重置功能 #### API 安全 - 所有管理员接口需要身份验证 - 支持跨域资源共享 (CORS) - 实现请求日志记录 - 敏感信息自动脱敏 ## 注意事项 1. **安全性**: 实际应用中应使用HTTPS协议 2. **令牌**: 示例中的access_token是JWT格式,需要妥善保存 3. **验证码**: - 实际应用中不应在响应中返回验证码 - 测试模式下会在控制台显示验证码,或通过调试接口获取 - 验证码有效期通常为5分钟 - 验证码登录要求邮箱已验证(email_verified=true) - 调试接口:`POST /auth/debug-verification-code` 可获取验证码详情 4. **用户ID**: 修改密码接口中的user_id应从JWT令牌中获取,而不是从请求体中传递 5. **错误处理**: 建议在客户端实现适当的错误处理和用户提示 6. **限流**: 建议对登录、注册等接口实施限流策略 7. **管理员权限**: - 管理员接口需要 role=9 的用户权限 - 需要在请求头中携带有效的JWT Token - Token格式:`Authorization: Bearer ` 8. **存储模式**: - 数据库模式:数据持久化存储在MySQL - 内存模式:数据存储在内存中,重启后丢失 9. **邮箱验证**: - 注册时如果提供邮箱,需要先获取验证码 - 支持重新发送验证码功能 - 调试接口仅用于开发环境 10. **验证码登录**: - 验证码登录需要用户邮箱已验证 - 支持邮箱和手机号两种方式 - 验证码类型为 `login_verification` - 与注册验证码是不同的验证码类型 ## 常见测试场景 ### 🔍 **前端开发者必测场景** #### **1. 用户注册完整流程** ```javascript // 场景:新用户完整注册流程 const testCompleteRegistration = async () => { const email = 'newuser@example.com'; // Step 1: 发送邮箱验证码 const codeResponse = await fetch('/auth/send-email-verification', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }); expect(codeResponse.status).toBe(206); // 测试模式 const codeData = await codeResponse.json(); expect(codeData.success).toBe(false); expect(codeData.error_code).toBe('TEST_MODE_ONLY'); // Step 2: 使用验证码注册 const registerResponse = await fetch('/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'newuser123', password: 'SecurePass123', nickname: '新用户', email: email, email_verification_code: codeData.data.verification_code }) }); expect(registerResponse.status).toBe(201); const registerData = await registerResponse.json(); expect(registerData.success).toBe(true); expect(registerData.data.access_token).toBeDefined(); }; ``` #### **2. 验证码登录完整流程** ```javascript // 场景:验证码登录完整流程 const testVerificationCodeLogin = async () => { const email = 'test@example.com'; // Step 1: 发送登录验证码 const codeResponse = await fetch('/auth/send-login-verification-code', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: email }) }); expect(codeResponse.status).toBe(206); // 测试模式 const codeData = await codeResponse.json(); expect(codeData.success).toBe(false); expect(codeData.error_code).toBe('TEST_MODE_ONLY'); // Step 2: 使用验证码登录 const loginResponse = await fetch('/auth/verification-code-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: email, verification_code: codeData.data.verification_code }) }); expect(loginResponse.status).toBe(200); const loginData = await loginResponse.json(); expect(loginData.success).toBe(true); expect(loginData.data.access_token).toBeDefined(); }; ``` #### **3. 登录失败处理** ```javascript // 场景:各种登录失败情况 const testLoginFailures = async () => { // 用户不存在 const response1 = await fetch('/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: 'nonexistent', password: 'password123' }) }); expect(response1.status).toBe(200); // 业务错误返回200 const data1 = await response1.json(); expect(data1.success).toBe(false); expect(data1.error_code).toBe('LOGIN_FAILED'); // 密码错误 const response2 = await fetch('/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: 'existinguser', password: 'wrongpassword' }) }); expect(response2.status).toBe(200); const data2 = await response2.json(); expect(data2.success).toBe(false); expect(data2.error_code).toBe('LOGIN_FAILED'); }; ``` #### **4. 频率限制测试** ```javascript // 场景:验证码发送频率限制 const testRateLimit = async () => { const email = 'test@example.com'; // 第一次发送 - 成功 const response1 = await fetch('/auth/send-email-verification', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }); expect(response1.status).toBe(206); // 测试模式 // 立即再次发送 - 被限制 const response2 = await fetch('/auth/send-email-verification', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }); expect(response2.status).toBe(429); const data2 = await response2.json(); expect(data2.message).toContain('请等待'); }; ``` #### **5. 管理员权限测试** ```javascript // 场景:管理员权限验证 const testAdminPermissions = async () => { // 普通用户尝试访问管理员接口 const userToken = 'user_token_here'; const response = await fetch('/admin/users', { headers: { 'Authorization': `Bearer ${userToken}` } }); expect(response.status).toBe(403); // 无效token访问 const response2 = await fetch('/admin/users', { headers: { 'Authorization': 'Bearer invalid_token' } }); expect(response2.status).toBe(401); // 正确的管理员token const adminToken = await getAdminToken(); const response3 = await fetch('/admin/users', { headers: { 'Authorization': `Bearer ${adminToken}` } }); expect(response3.status).toBe(200); }; ``` #### **6. 用户状态影响登录** ```javascript // 场景:不同用户状态的登录测试 const testUserStatusLogin = async () => { // 正常用户登录 const activeResponse = await login('activeuser', 'password'); expect(activeResponse.success).toBe(true); // 锁定用户登录 const lockedResponse = await login('lockeduser', 'password'); expect(lockedResponse.success).toBe(false); expect(lockedResponse.message).toContain('锁定'); // 禁用用户登录 const bannedResponse = await login('banneduser', 'password'); expect(bannedResponse.success).toBe(false); expect(bannedResponse.message).toContain('禁用'); }; ``` ### 📝 **边界条件测试清单** #### **输入验证测试** - [ ] 空字符串输入 - [ ] 超长字符串输入(用户名>50字符) - [ ] 特殊字符输入(SQL注入尝试) - [ ] 无效邮箱格式 - [ ] 弱密码(少于8位、纯数字、纯字母) - [ ] 无效验证码格式(非6位数字) #### **状态边界测试** - [ ] 验证码过期边界(5分钟) - [ ] 验证码尝试次数边界(3次) - [ ] 频率限制边界(1分钟、1小时) - [ ] Token过期边界(8小时) - [ ] 用户状态变更后的立即登录 #### **并发测试** - [ ] 同时发送多个验证码请求 - [ ] 同时使用相同验证码验证 - [ ] 并发用户注册相同用户名 - [ ] 并发管理员操作同一用户 ### 🚨 **错误恢复测试** #### **网络异常处理** ```javascript // 场景:网络中断恢复 const testNetworkRecovery = async () => { // 模拟网络中断 mockNetworkError(); try { await login('testuser', 'password'); fail('应该抛出网络错误'); } catch (error) { expect(error.message).toContain('网络'); } // 恢复网络 restoreNetwork(); // 重试应该成功 const response = await login('testuser', 'password'); expect(response.success).toBe(true); }; ``` #### **服务降级测试** ```javascript // 场景:邮件服务不可用时的降级 const testEmailServiceDegradation = async () => { // 邮件服务不可用时,应该返回测试模式 const response = await fetch('/auth/send-email-verification', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'test@example.com' }) }); expect(response.status).toBe(206); const data = await response.json(); expect(data.error_code).toBe('TEST_MODE_ONLY'); expect(data.data.is_test_mode).toBe(true); }; ``` ### 🔧 **自动化测试脚本** #### **快速冒烟测试** ```bash #!/bin/bash # 快速验证所有关键接口 BASE_URL="http://localhost:3000" echo "🚀 开始API冒烟测试..." # 1. 应用状态检查 echo "1. 检查应用状态..." curl -f "$BASE_URL/" > /dev/null || exit 1 # 2. 验证码发送 echo "2. 测试验证码发送..." RESPONSE=$(curl -s -X POST "$BASE_URL/auth/send-email-verification" \ -H "Content-Type: application/json" \ -d '{"email":"test@example.com"}') CODE=$(echo "$RESPONSE" | jq -r '.data.verification_code') if [ "$CODE" = "null" ]; then echo "❌ 验证码发送失败" exit 1 fi # 3. 用户注册 echo "3. 测试用户注册..." USERNAME="smoketest_$(date +%s)" curl -f -X POST "$BASE_URL/auth/register" \ -H "Content-Type: application/json" \ -d "{\"username\":\"$USERNAME\",\"password\":\"Test123456\",\"nickname\":\"冒烟测试\",\"email\":\"test@example.com\",\"email_verification_code\":\"$CODE\"}" > /dev/null || exit 1 # 4. 用户登录 echo "4. 测试用户登录..." curl -f -X POST "$BASE_URL/auth/login" \ -H "Content-Type: application/json" \ -d "{\"identifier\":\"$USERNAME\",\"password\":\"Test123456\"}" > /dev/null || exit 1 echo "✅ 冒烟测试通过!" ``` #### **性能基准测试** ```bash #!/bin/bash # 简单的性能基准测试 echo "📊 开始性能基准测试..." # 并发登录测试 echo "测试并发登录性能..." ab -n 100 -c 10 -T 'application/json' -p login_data.json http://localhost:3000/auth/login # 验证码发送性能测试 echo "测试验证码发送性能..." ab -n 50 -c 5 -T 'application/json' -p email_data.json http://localhost:3000/auth/send-email-verification echo "📈 性能测试完成,请查看上述结果" ``` ### 💡 **测试技巧和建议** #### **1. 测试数据管理** - 使用时间戳生成唯一的测试用户名 - 测试完成后清理测试数据 - 使用专门的测试邮箱域名 #### **2. 异步操作处理** - 验证码生成后立即使用,避免过期 - 注意频率限制的时间窗口 - 使用适当的等待时间 #### **3. 错误场景覆盖** - 测试所有可能的HTTP状态码 - 验证错误消息的准确性 - 测试错误恢复机制 #### **4. 安全测试** - 尝试SQL注入和XSS攻击 - 测试权限绕过 - 验证敏感信息不泄露 这些测试场景和边界条件将帮助前端开发者进行全面的API测试,确保应用的稳定性和安全性。 - **v1.1.0** (2025-12-25): - **新增验证码登录功能** - 添加验证码登录接口 (POST /auth/verification-code-login) - 添加发送登录验证码接口 (POST /auth/send-login-verification-code) - 支持邮箱和手机号验证码登录 - 完善验证码相关错误处理和限流机制 - **文档完善** - 更新API文档,新增验证码登录相关说明 - 修正错误码与实际响应的一致性 - 添加验证码登录测试场景和使用示例 - 更新OpenAPI规范文档 - **接口数量更新**:21个 → 23个API接口 - **用户认证接口**:11个 → 13个接口 - **v1.0.0** (2025-12-24): - **完整的API文档更新** - 重新整理接口分类,将用户管理接口独立分类 - 确保文档与实际运行的服务完全一致 - 验证所有接口的请求参数和响应格式 - **修复HTTP状态码问题**:所有接口现在根据业务结果返回正确状态码 - **更新限流配置**:注册接口限制调整为10次/5分钟(开发环境) - **应用状态接口** (1个) - `GET /` - 获取应用状态 - **用户认证接口** (13个) - 用户登录、注册、GitHub OAuth - 密码重置和修改功能 - 邮箱验证相关接口 - 调试验证码接口 - **新增**:清除限流记录接口(开发环境) - **管理员接口** (6个) - 管理员登录和用户管理 - 用户列表和详情查询 - 密码重置功能 - 日志管理和下载 - **用户管理接口** (3个) - 用户状态管理 (active/inactive/locked/banned/deleted/pending) - 单个用户状态修改接口 - 批量用户状态修改接口 - 用户状态统计接口 - **安全增强功能** - 频率限制中间件 (Rate Limiting) - 已调整配置 - 维护模式中间件 (Maintenance Mode) - 内容类型验证中间件 (Content Type Validation) - 请求超时拦截器 (Request Timeout) - 用户状态检查和权限控制 - **修复**:HTTP状态码现在正确反映业务执行结果 - **总计接口数量**: 23个API接口 - 完善错误代码和使用示例 - 修复路由冲突问题 - 确保文档与实际测试效果一致 - **重要修复**:解决了业务失败但返回成功状态码的问题