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-03-platform-sso-rea...

7.7 KiB

数字人民币系统:主平台单点登录与只读用户设计

1. 目标与边界

数字人民币系统需要同时支持:

  • 从天泽主平台跳转后的无感单点登录;
  • 用户直接访问数字人民币系统后,通过学校 CAS 统一认证登录;
  • 仅教师和学生两种业务角色。

主平台不做任何改造。用户、教师/学生身份与角色的唯一主数据源为主平台;数字人民币系统不提供用户、角色或用户角色的人工增删改接口。

“只读”是指面向用户和管理端只读。为满足角色复制要求,系统内部的受控同步任务会维护本地镜像表,不接受外部写入。

2. 已验证的现状

主平台不是 OAuth2/OIDC 身份提供方:它使用学校 CAS 作为单点登录源,并在登录后签发自定义 Token。

  • CAS 配置位于主平台 web/src/main/resources/application.properties
  • CAS Filter 配置位于 web/src/main/java/cn/jlw/Interceptor/CasConfig.java
  • 自定义 Token 的生成和 HMAC 验证算法位于 web/src/main/java/cn/jlw/token/TokenService.java
  • CAS 用户到教师/学生的映射位于 web/src/main/java/com/ibeetl/jlw/service/CasUserLoginService.java

该 Token 的 HMAC 密钥由相应主平台教师/学生记录的 addTime 派生。因此,数字人民币系统不能只解析 Token 后信任其中声明;验签必须结合主平台只读数据完成。

3. 总体架构

新增独立的认证桥接服务Authentication Bridge

  1. 对数字人民币系统提供 OAuth2/OIDC 授权码模式;
  2. 对学校 CAS 作为 CAS Client
  3. 接收并验证主平台跳转时携带的自定义 Token
  4. 使用主平台只读数据同步用户身份和教师/学生角色;
  5. 使用 RS256 签发 OIDC 令牌,发布 OpenID Provider Configuration 与 JWKS。

数字人民币后端作为 OAuth2/OIDC Client完成 OIDC 回调后签发自己的短期 API JWT。所有业务接口只认可本系统 JWT不接受主平台 Token。

主平台 ──主平台 Token 跳转──> 认证桥接服务 ──授权码回调──> 数字人民币系统
学校 CAS ──CAS 身份认证──────> 认证桥接服务
数字人民币系统 ──只读用户/角色快照──> 本地 MySQL
认证桥接服务 ──SELECT only────────> 主平台数据库

4. 登录流程

4.1 从主平台跳转

  1. 主平台通过既有跳转链接将 token 传给桥接服务的 GET /bridge/sso/platform?token=...
  2. 桥接服务验证 Token加载主平台教师/学生身份及状态;
  3. 桥接服务完成或刷新本地快照,并创建仅一次的 OAuth2 授权码;
  4. 浏览器被重定向到数字人民币系统的固定 OIDC 回调地址;
  5. 数字人民币后端以授权码换取并验证 OIDC Token签发自身访问 JWT 与刷新令牌。

4.2 用户直接访问

  1. 数字人民币系统的 GET /api/v1/auth/sso/login 发起桥接服务 OAuth2 授权码流程;
  2. 桥接服务跳转学校 CAS已登录 CAS 的用户无感通过,未登录用户在学校认证页登录;
  3. CAS 回调桥接服务后,桥接服务从主平台只读数据识别教师或学生;
  4. 后续流程与 4.1 的第 3 至 5 步相同。

这就是独立登录:直接进入数字人民币系统并使用学校统一账号认证,而不是维护第二套用户名和密码。

4.3 退出

数字人民币系统退出只撤销自身刷新令牌和本地会话;默认不退出学校 CAS 或主平台,避免跨系统连带登出。

5. 身份、角色与只读快照

本地表是主平台的投影,不是主数据:

用途 写入者
platform_user_snapshot 主平台用户 ID、账号、姓名、状态、同步时间 同步任务
role 固定角色 TEACHERSTUDENT 数据库迁移
user_role 主平台用户到教师/学生角色的镜像 同步任务
platform_identity_link 主平台用户 ID 与本系统内部主体的稳定映射 同步任务
auth_refresh_token 本系统可撤销刷新令牌摘要 认证模块

角色映射以主平台 jobType1 为准:JT_S_02 映射为 TEACHERJT_S_03 映射为 STUDENT。其他身份不允许进入本系统。每次成功登录均即时刷新;同时执行首次全量和定时增量同步。

不按姓名、手机号或可变用户名自动合并用户。主平台用户 ID 是跨同步、角色和身份关联的稳定键。

6. Token 验证与安全规则

桥接服务的主平台 Token 适配器按以下顺序处理:

  1. 限制 Token 长度、字符集及主平台约定的 JWT 加登录时间戳结构;
  2. 将未验签的用户 ID 和身份类型仅用于定位候选主平台记录;
  3. 读取候选教师或学生记录的 addTime,按主平台算法重建 HMAC 密钥并验证签名;
  4. 校验用户状态、身份类型和角色映射;
  5. 以 Token 的 SHA-256 指纹进行一次性消费,跳转 Token 最长有效期为 120 秒;
  6. 验签成功后不透传 Token而是进入 OAuth2/OIDC 授权码流程。

Token 出现在 URL 的风险通过以下措施降低:

  • 该参数仅由桥接入口接收,成功或失败后立即重定向到不含 Token 的 URL
  • 所有相关响应设置 Cache-Control: no-storeReferrer-Policy: no-referrer
  • 反向代理、应用访问日志和异常日志必须对 token 参数脱敏;
  • 仅允许 HTTPS、固定回调地址、statenonce 与 PKCE
  • 授权码为一次性且短时有效。

桥接服务与数字人民币系统间使用 RS256数字人民币系统通过 JWKS 验签并校验 issaudexpnonce。不得共享 HMAC 密钥。

7. 数据库权限与运行限制

桥接服务使用独立的主平台数据库只读账号,仅授予所需用户、教师、学生及身份关联表的 SELECT 权限。严禁授予 INSERTUPDATEDELETECREATEALTER 或 DDL 权限。

数字人民币系统不得通过接口修改 platform_user_snapshotroleuser_roleplatform_identity_link。现有脚手架中的本地引导管理员登录仅限开发期;实现本设计后,生产环境将禁用该本地密码入口,教师和学生均走统一认证。

8. DDD 边界

  • identity 限定上下文:只读用户快照、身份链接、教师/学生角色投影;
  • security 限定上下文:本系统 JWT、刷新令牌、授权回调与当前用户
  • platform-integration 防腐层:主平台 Token 验签、只读查询、CAS/OIDC 桥接;
  • 业务域只依赖 CurrentActor(主平台用户 ID、角色、状态不依赖 CAS、OIDC 或主平台 Token 细节。

9. 接口边界

保留或新增的公开认证入口:

  • GET /api/v1/auth/sso/login:发起直接统一认证;
  • GET /login/oauth2/code/platform-bridge:固定 OIDC 回调;
  • GET /api/v1/auth/me:读取当前用户与角色;
  • POST /api/v1/auth/logout:撤销本系统会话。

桥接服务专用入口:

  • GET /bridge/sso/platform?token=...:主平台跳转入口;
  • 标准 OIDC discovery、authorize、token 与 JWKS 端点。

不提供用户、角色、用户角色的 CRUD API。

10. 验收与测试

  • 主平台教师 Token 映射 TEACHER,学生 Token 映射 STUDENT
  • 伪造、篡改、过期、重放或身份不匹配的 Token 均被拒绝;
  • 被禁用用户和非教师/学生身份均被拒绝;
  • CAS 有会话与无会话两种直接登录流程均可完成;
  • OAuth2 statenonce、PKCE、回调地址和 JWKS 验签均有集成测试;
  • 数据库账号只能 SELECT尝试任何写操作均失败
  • 用户、角色和用户角色写接口不存在或返回拒绝结果;
  • Swagger 中不展示用户/角色 CRUD认证入口与错误码有文档。