Files
huang 18f35f3ef4 feat: 完成B端认证系统和商户管理模块测试补全
主要变更:
- 新增B端认证系统(后台+H5):登录、登出、Token刷新、密码修改
- 完善商户管理和商户账号管理功能
- 补全单元测试(ShopService: 72.5%, ShopAccountService: 79.8%)
- 新增集成测试(商户管理+商户账号管理)
- 归档OpenSpec提案(add-shop-account-management, implement-b-end-auth-system)
- 完善文档(使用指南、API文档、认证架构说明)

测试统计:
- 13个测试套件,37个测试用例,100%通过率
- 平均覆盖率76.2%,达标

OpenSpec验证:通过(strict模式)
2026-01-15 18:15:17 +08:00

144 lines
7.0 KiB
Markdown
Raw Permalink 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.
# b-end-auth Specification
## Purpose
TBD - created by archiving change implement-b-end-auth-system. Update Purpose after archive.
## Requirements
### Requirement: B 端用户登录
系统 SHALL 支持后台管理员、代理商和企业用户通过用户名/手机号和密码进行登录认证。
#### Scenario: 后台管理员登录成功
- **WHEN** 用户访问 `POST /api/admin/login` 并提供有效的用户名和密码
- **THEN** 系统验证凭据,生成 access token 和 refresh token返回 token 和用户信息
#### Scenario: H5 端代理商登录成功
- **WHEN** 用户访问 `POST /api/h5/login` 并提供有效的用户名和密码
- **THEN** 系统验证凭据,生成 access token 和 refresh token返回 token 和用户信息
#### Scenario: 登录失败 - 凭据无效
- **WHEN** 用户提供错误的用户名或密码
- **THEN** 系统返回 401 错误,错误码 1040消息"用户名或密码错误"
#### Scenario: 登录失败 - 账号已禁用
- **WHEN** 用户账号状态为禁用
- **THEN** 系统返回 403 错误,错误码 1041消息"账号已被锁定或禁用"
### Requirement: Token 管理
系统 SHALL 使用 Redis 存储的双令牌机制管理用户会话,包括 access token24小时有效和 refresh token7天有效
#### Scenario: 生成 Token 对
- **WHEN** 用户登录成功
- **THEN** 系统生成随机 UUID 作为 access token 和 refresh token将用户信息UserID、UserType、ShopID、EnterpriseID、Username、Device、IP、LoginTime存储到 Redis设置相应的 TTL
#### Scenario: 验证 Access Token
- **WHEN** 请求受保护的 API 端点时,在 Authorization 头中提供 Bearer token
- **THEN** 系统从 Redis 查询 token 对应的用户信息,验证 token 有效性,将用户信息注入到请求上下文
#### Scenario: Token 过期
- **WHEN** access token 超过 24 小时未使用
- **THEN** Redis 自动删除 token后续验证返回 401 错误,错误码 1002消息"令牌无效或已过期"
#### Scenario: Token 不存在
- **WHEN** 提供的 token 在 Redis 中不存在
- **THEN** 系统返回 401 错误,错误码 1002消息"令牌无效或已过期"
### Requirement: 用户登出
系统 SHALL 支持用户主动登出,撤销当前使用的 access token 和 refresh token。
#### Scenario: 成功登出
- **WHEN** 用户访问 `POST /api/admin/logout``POST /api/h5/logout` 并提供有效的 token
- **THEN** 系统从 Redis 删除对应的 access token 和 refresh token并从用户 token 列表中移除,返回成功响应
#### Scenario: 已登出的 Token 无法再使用
- **WHEN** 用户登出后,使用相同的 token 访问受保护端点
- **THEN** 系统返回 401 错误,消息"令牌无效或已过期"
### Requirement: Token 刷新
系统 SHALL 支持使用 refresh token 刷新 access token延长会话有效期而无需重新登录。
#### Scenario: 成功刷新 Access Token
- **WHEN** 用户访问 `POST /api/admin/refresh-token``POST /api/h5/refresh-token` 并提供有效的 refresh token
- **THEN** 系统验证 refresh token生成新的 access token保持 refresh token 不变),返回新的 access token
#### Scenario: Refresh Token 无效
- **WHEN** 提供的 refresh token 不存在或已过期
- **THEN** 系统返回 401 错误,错误码 1002消息"刷新令牌无效或已过期"
### Requirement: 获取当前用户信息
系统 SHALL 支持已认证用户查询当前用户的详细信息和权限列表。
#### Scenario: 成功获取用户信息
- **WHEN** 用户访问 `GET /api/admin/me``GET /api/h5/me` 并提供有效的 access token
- **THEN** 系统从 token 解析用户 ID查询数据库获取用户信息ID、用户名、手机号、用户类型、店铺 ID、企业 ID和权限列表返回完整的用户信息
#### Scenario: Token 无效时无法获取用户信息
- **WHEN** 提供无效或过期的 token
- **THEN** 系统在中间件层拦截,返回 401 错误
### Requirement: 修改密码
系统 SHALL 支持已认证用户修改自己的密码,并在密码修改后撤销所有旧 token。
#### Scenario: 成功修改密码
- **WHEN** 用户访问 `PUT /api/admin/password``PUT /api/h5/password`,提供旧密码和新密码
- **THEN** 系统验证旧密码,使用 bcrypt 哈希新密码并更新数据库,撤销用户所有 token包括当前使用的 token返回成功响应
#### Scenario: 旧密码错误
- **WHEN** 提供的旧密码不正确
- **THEN** 系统返回 400 错误,错误码 1043消息"旧密码不正确"
#### Scenario: 密码修改后旧 Token 失效
- **WHEN** 用户修改密码后,使用旧的 token 访问任何端点
- **THEN** 系统返回 401 错误,消息"令牌无效或已过期"
### Requirement: 多端认证隔离
系统 SHALL 通过认证中间件实现后台和 H5 端的用户类型隔离,确保不同端点只能被对应用户类型访问。
#### Scenario: 后台端点用户类型验证
- **WHEN** 用户访问 `/api/admin/*` 端点
- **THEN** 认证中间件验证用户类型必须为 SuperAdmin(1)、Platform(2) 或 Agent(3),否则返回 403 错误
#### Scenario: H5 端点用户类型验证
- **WHEN** 用户访问 `/api/h5/*` 端点
- **THEN** 认证中间件验证用户类型必须为 Agent(3) 或 Enterprise(4),否则返回 403 错误
#### Scenario: 公开端点无需认证
- **WHEN** 用户访问 `/api/admin/login``/api/admin/refresh-token``/api/h5/login``/api/h5/refresh-token`
- **THEN** 中间件跳过认证检查,允许匿名访问
### Requirement: Token 批量撤销
系统 SHALL 支持撤销指定用户的所有 token用于密码修改或账号禁用场景。
#### Scenario: 撤销用户所有 Token
- **WHEN** 调用 `RevokeAllUserTokens(userID)` 方法(内部使用,密码修改时触发)
- **THEN** 系统从 Redis 查询用户 token 列表(`auth:user:{userID}:tokens`),删除所有 access token 和 refresh token 及其对应的用户信息,清空 token 列表
#### Scenario: 撤销不存在用户的 Token
- **WHEN** 调用 `RevokeAllUserTokens` 但用户没有任何活跃 token
- **THEN** 系统不报错,直接返回成功
### Requirement: 并发安全
系统 SHALL 保证 Token 管理器在高并发场景下的线程安全和数据一致性。
#### Scenario: 并发生成 Token
- **WHEN** 同一用户在不同设备上同时登录(多个并发请求)
- **THEN** 每个请求生成独立的 token 对,所有 token 都有效,互不干扰
#### Scenario: 并发撤销 Token
- **WHEN** 多个请求同时撤销同一 token
- **THEN** Redis 操作原子性保证只有一个请求成功删除,其他请求不报错
### Requirement: 性能要求
系统 SHALL 满足以下性能指标。
#### Scenario: 登录响应时间
- **WHEN** 用户发起登录请求
- **THEN** API P95 响应时间 < 200msP99 响应时间 < 500ms
#### Scenario: Token 验证响应时间
- **WHEN** 请求受保护端点触发 token 验证
- **THEN** Redis 查询时间 < 50ms
#### Scenario: Token 生成唯一性
- **WHEN** 系统生成 token
- **THEN** 使用 UUID v4 保证全局唯一性,碰撞概率 < 10^-15