You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digital-rmb-backend/docs/superpowers/specs/2026-08-04-current-user-con...

73 lines
4.2 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 当前用户上下文设计
## 目标
为后端业务代码提供统一的当前用户读取能力,并将 `GET /api/v1/auth/me` 扩展为返回主平台 Token 中经验证的完整用户资料。
## 范围
- SSO 成功后,从已验证的主平台 Token payload 提取并本地持久化用户资料。
- 提供可注入的当前用户读取服务,供任意已认证业务接口使用。
- 扩展 `/api/v1/auth/me` 返回的 DTO。
- 不改变本系统 JWT 的主体语义、角色授权方式或本地账号密码登录流程。
## 用户资料契约
当前用户对象和 `/api/v1/auth/me``data` 使用下列 camelCase 字段。`roleid` 与 `studentid` 保持主平台字段拼写,以避免调用方转换。
| 字段 | 来源 | 说明 |
| --- | --- | --- |
| `schoolId` / `schoolName` | Token `schoolId` / `schoolName` | 学校标识与名称 |
| `collegeId` / `collegeName` | Token `collegeId` / `collegeName` | 院系标识与名称 |
| `majorId` / `majorName` | Token `majorId` / `majorName` | 专业标识与名称 |
| `roleid` | Token `roleid` | 主平台原始角色 ID不替换为本系统角色 ID |
| `userId` | Token `userId` | 主平台用户 ID也是本地用户 ID 与 JWT subject |
| `username` | Token `username` | 用户登录账号 |
| `name` | Token `name` | 用户姓名 |
| `classId` / `className` | Token `classId` / `className` | 班级标识与名称 |
| `studentid` | Token `studentid` | 学号/学生标识 |
标识类字段以字符串持久化和返回,以兼容主平台可能出现的非纯数字编码;`userId` 是唯一的数值主键,解析为 `long`
## 架构与数据流
```text
主平台 Token
-> PlatformTokenVerifier验签、校验必填资料
-> PlatformActor完整的已验证身份
-> PlatformIdentityProjectionService事务内更新 sys_user、快照、授权角色
-> platform_user_snapshot
本系统 JWT subject(userId)
-> CurrentUserService
-> platform_user_snapshot
-> 业务代码 / GET /api/v1/auth/me
```
`PlatformTokenVerifier` 只能在签名、登录时间和现有身份声明均通过后,才构造含完整资料的 `PlatformActor`。它校验 `userId`、`username`、`name`、`roleid` 必填,并将 `roleid` 映射为既有 `TEACHER``STUDENT` 以保留 Spring Security 授权行为。学校、院系、专业、班级和 `studentid` 允许为空,以兼容教师等不具备学生组织信息的身份。
`PlatformIdentityProjectionService` 在现有事务中更新扩展后的 `platform_user_snapshot`。快照是当前用户资料的唯一读取源;业务请求不会重新解析主平台 Token也不会查询主平台数据库。
`CurrentUserService` 位于 `security.application`,从 Spring Security 的 `Jwt` 读取 subject查询快照并返回不可变当前用户对象。未认证、subject 不是正整数或快照不存在时抛出既有 `UNAUTHORIZED` 业务异常。Controller 只调用该服务并将结果转换/直接作为响应 DTO 返回,不直接访问 Mapper。
## 持久化
扩展 `platform_user_snapshot`,增加学校、院系、专业、班级、主平台原始角色 ID 和学生标识字段。`schema.sql` 需同时覆盖新环境建表和已有数据库的幂等升级;不引入 Flyway。快照中保留 `role_key` 作为本系统授权映射,新增的 `roleid` 独立保存主平台原始值。
## API 与错误处理
`GET /api/v1/auth/me` 仍要求本系统 Bearer JWT并返回既有 `ApiResponse` 包装。成功响应只包含上述用户资料字段,不包含密码、主平台 Token、刷新令牌或快照同步时间。未认证或快照缺失时维持现有未授权错误语义。
## 测试
- Token 验证测试:完整资料被解析进已验证身份;缺少必填字段的 Token 被拒绝。
- 身份投影测试:扩展资料写入并在重复 SSO 时更新,不产生重复角色关联。
- 当前用户服务/接口测试:持有本系统 JWT 时能读取全部字段;无效 subject 与不存在快照返回未授权。
- 运行项目规定的 Maven 测试与打包命令。
## 非目标
- 不向业务 Controller 暴露用户、角色或快照 CRUD。
- 不在每次业务请求时调用主平台或解析主平台 Token。
- 不在本系统 JWT 中复制完整用户资料。