3.6 KiB
本地 Token SSO 设计
目标
数字人民币后端不连接、不读取主平台数据库。主平台通过跳转链接携带 JWT;后端使用双方约定的共享密钥验证该 JWT,并仅使用 Token 中的用户数据创建或更新本地用户,然后直接签发本系统 JWT 并重定向给前端。
本地账号密码登录必须保留。主平台 Token 中携带的密码是本地密码的同步来源:每次 SSO 登录成功后,后端都将该密码 BCrypt 编码后写入本地用户表。因此,用户在主平台修改密码并再次通过 SSO 跳转后,可立即使用新密码独立登录本系统。
边界与依赖
保留的外部依赖只有主平台 Token 的共享密钥;不保留任何主平台数据源、数据库表查询、同步任务或远程身份仓储。
主平台 Token 采用 PEVC 示例相同的标准三段 JWT 与 HMAC 共享密钥验签。运行时通过环境变量配置共享密钥,禁止将其提交到代码库。
必需 claim:
userId:主平台用户 ID,也是本地sys_user.id。username:本地登录账号。password:主平台当前明文密码,仅用于立即 BCrypt 编码后保存,不记录到日志、快照或响应。roleid:3映射为TEACHER,其他值映射为STUDENT。
可选 claim:name、schoolId、schoolName、classId、className、collegeId、collegeName、studentNo、realName。这些字段仅在本地快照或本系统 JWT 扩展字段中使用。
SSO 流程
- 前端或主平台访问
GET /api/v1/auth/sso?token={parentToken}。 - 后端使用共享密钥验证 JWT 的签名与有效期,并提取必需 claim。
- 后端以
userId查询本地sys_user。 - 若不存在,使用 Token 数据创建本地用户、用户快照和
sys_user_role;若存在,更新账号、启用状态、快照、角色关联及 BCrypt 密码散列。 - 后端以本地用户信息签发数字人民币系统 JWT,并以 302 重定向至
{frontend-callback-url}/sso-callback?token={digitalRmbToken}。
本系统 JWT 的 subject 为本地 userId,并包含 preferred_username 与本地角色列表。SSO 入口不再生成或消费一次性交换码。
数据一致性与错误处理
用户、快照、角色关联和密码散列更新在同一个本地数据库事务内完成。已验证 Token 的用户同步必须幂等:同一用户多次跳转不会产生重复用户或角色行。
签名无效、过期、缺失必需 claim、非法 userId 或空账号/密码时,拒绝登录并重定向至前端登录页的 SSO 失败状态。不得在响应、日志或异常中输出原始 Token 或密码。
删除项
删除以下主平台数据库依赖:
platformReadOnlyDataSource与platformNamedParameterJdbcTemplate。PlatformIdentityRepository的远程实现及相关主平台查询 SQL。PlatformIdentitySyncJob及platform-integration.sync配置。- 依赖远程身份数据验签的旧四段 Token 校验逻辑。
删除一次性交换码的 SSO 路径及其服务调用。为避免破坏现有数据库数据,既有 auth_login_exchange_code 表可暂时保留但不再被应用访问。
验证标准
- 应用启动时只创建一个本地业务数据源。
- 有效主平台 JWT 可创建本地用户并直接重定向携带本系统 JWT。
- 已存在用户每次 SSO 后密码散列都会更新;使用 Token 中的新密码可通过本地
/api/v1/auth/login登录。 - 无效签名、过期 Token 或缺失必需字段不能创建/更新本地用户。
- 本地账号密码登录、当前用户查询和注销的既有行为保持可用。