# OneOS(RuoYi-Cloud)与车辆数据中台统一登录及业务权限集成方案 更新时间:2026-07-24 状态:首期代码已完成,待部署配置与测试环境端到端验收 责任团队:OneOS AI(Codex)、车辆数据中台 AI(Codex) ## 0. 本次交付状态 截至 2026-07-24,首期方案已在双边落地: - OneOS `ln-cloud`:`dev-ssl-codex` 分支; - OneOS `ln-one-os-web`:`dev-ssl-codex` 分支; - OneOS 已实现 Sa-Token 登录态校验、60 秒一次性 Ticket、Redis 原子核销、Service Token + HMAC + 时间戳 + Request ID 防重放; - OneOS 已提供车辆数据中台中转页和菜单/权限初始化 SQL; - 车辆数据中台已实现 introspection 客户端、Ticket 兑换接口、外部账号即时同步、本地不透明会话和回调页; - `vehicle:scope:department` 映射为 `department`;未具备该权限的用户映射为 `responsible`; - 中台继续在服务端按 `platform_user_business_scope` 计算 VIN,不信任前端筛选。 部署时仍需完成:生成双边一致的密钥、发布 Nacos 配置、执行双边 SQL、为 OneOS 角色分配入口/部门权限,并完成两类账号验收。 ## 1. 方案目标 用户已经登录 OneOS 后,从 OneOS 菜单进入车辆数据中台,应当: 1. 不再次输入用户名和密码; 2. 车辆数据中台能够确认用户身份、启停状态、部门、角色和业务负责人 ID; 3. 部门级业务负责人只能查看其授权部门的车辆; 4. 普通业务人员只能查看 `responsible_user_id` 为本人的车辆; 5. 用户不能通过修改 URL、请求头、请求体或前端状态扩大车辆范围; 6. OneOS 退出、停用或权限变更后,中台权限在约定时间内失效; 7. 两套系统不共享数据库账号、Redis、JWT 密钥和浏览器登录 Cookie; 8. 任一鉴权、数据映射或业务范围异常均失败关闭,不回退为全量车辆。 ## 2. 当前基础与缺口 ### 2.1 已具备能力 车辆数据中台已经具备: - 本地账号、菜单权限、车辆 VIN Scope 和服务端强制过滤; - OneOS 业务车辆只读投影; - 部门、业务负责人、客户、运营状态多选筛选; - `platform_user.auth_provider + external_subject` 外部身份映射字段; - `platform_user_business_scope` 业务权限配置; - `department` 和 `responsible` 两种业务范围计算; - `IdentityAdapter` 外部身份适配接口; - 30 秒以内的主体缓存和失败关闭逻辑。 ### 2.2 尚未具备能力 - OneOS 尚未提供正式 SSO Ticket 或 OIDC 接口; - 车辆中台尚未注册实际的 RuoYi/OneOS `IdentityAdapter`; - 车辆中台前端尚无 OneOS 回调完成页; - 双方尚未确认稳定角色编码、部门负责人权限编码和用户 ID 映射; - 尚未完成双账号、跨部门和停用用户的端到端联调。 ## 3. 技术决策 ### 3.1 首期采用一次性 Ticket 首期采用: > RuoYi 登录态验证 + 一次性 SSO Ticket + 服务端 introspection + 车辆中台本地会话 理由: - 当前 OneOS 基于 RuoYi-Cloud-Plus 2.5.3 和 Sa-Token,完整 `LoginUser` 保存在 Token Session/Redis; - 仅离线解析 JWT 无法可靠判断 Redis 登录态、用户停用和当前权限; - 共享 OneOS Redis、JWT Secret 或 Cookie 会造成强耦合和较大安全风险; - 一次性 Ticket 复用 `LoginHelper.getLoginUser()` 和当前 Sa-Token 登录态,实施范围小; - OneOS Token 不进入车辆中台 URL、日志和存储; - 车辆中台继续使用自己的会话,现有 API 和前端改动可控。 ### 3.2 后续升级路径 若 OneOS 后续建设标准 OIDC,可将 Ticket/introspection 替换为: - Authorization Code; - PKCE; - OIDC Discovery; - JWKS 非对称签名验证; - 标准 `iss/aud/sub/iat/exp/jti` 声明。 业务权限映射、车辆 Scope 和本地会话模型保持不变。 ### 3.3 明确禁止的方案 - URL 直接传递 `userId`、`deptId`、`role`; - URL 传递 OneOS Access Token; - 车辆中台读取 OneOS Redis; - 双方共享 JWT 对称签名密钥; - 信任普通 `X-User-Id`、`X-Dept-Id` 等转发头; - 通过“业务一部”“部门负责人”等显示名称判断权限; - 前端根据角色自行过滤车辆; - Scope 为空时解释为“不限制”。 ## 4. 总体架构 ```mermaid sequenceDiagram participant U as 用户浏览器 participant OF as OneOS 前端 participant OA as OneOS Auth/Gateway participant VP as 车辆数据中台 API participant VW as 车辆数据中台 Web participant DB as 中台权限和业务投影 U->>OF: 已登录 OneOS U->>OF: 点击车辆数据中台 OF->>OA: POST /auth/sso/vehicle-platform/tickets Note over OF,OA: 携带当前 RuoYi Bearer Token OA->>OA: TokenService.getLoginUser() OA->>OA: 校验用户、部门和角色 OA-->>OF: 返回 60 秒单次 Ticket OF->>VW: 跳转 /auth/oneos/callback?ticket=... VW->>VP: POST /api/v2/auth/oneos/exchange VP->>OA: POST /inner/v1/sso/vehicle-platform/introspect Note over VP,OA: 服务身份 + HMAC + Ticket OA->>OA: 原子消费 Ticket OA-->>VP: 返回已验证用户声明 VP->>DB: 映射 platform_user 和业务 Scope VP->>DB: 按部门或负责人计算 VIN VP-->>VW: 返回中台 Access Token 和 Session VW->>VW: 保存到 sessionStorage VW->>U: 进入 /vehicles ``` ## 5. 身份、角色与权限模型 ### 5.1 OneOS 权威字段 OneOS 是以下字段的身份权威来源: - `userId`:RuoYi `sys_user.user_id`,按字符串传输; - `username`; - `nickname`; - `status/active`; - `deptId`; - `tenantId`; - `roleKeys`; - `permissions`; - OneOS 当前登录有效期。 ### 5.2 中台权威字段 车辆数据中台是以下内容的最终授权执行方: - 中台账号是否允许登录; - 中台菜单权限; - OneOS 角色到中台业务范围的映射; - 当前有效业务车辆 VIN 集合; - 单车、列表、地图、轨迹、历史、统计和导出的服务端 Scope; - 中台会话、审计和拒绝决策。 ### 5.3 推荐的 RuoYi 权限编码 OneOS 新增稳定权限编码: ```text vehicle:platform:access vehicle:scope:department ``` 映射规则: | OneOS 条件 | 中台 Scope | 可见车辆 | |---|---|---| | 用户停用 | denied | 无 | | 无 `vehicle:platform:access` | denied | 无 | | 有 `vehicle:scope:department` | `department` | `department_id IN departmentIds` | | 无部门级权限且有 `userId` | `responsible` | `responsible_user_id = userId` | | Scope 必需字段缺失 | denied | 无 | 约束: - 不把 OneOS `admin` 自动映射为中台 `admin`; - 部门级权限以权限编码判断,不以角色显示名称判断; - 首期 `departmentIds=[deptId]`,如需多部门必须由 OneOS 明确返回稳定 ID 数组; - `responsible_user_id` 必须确认与 OneOS `sys_user.user_id` 使用同一 ID; - 若两者不一致,必须提供权威映射,不允许按姓名匹配。 ## 6. OneOS SSO 接口契约 ### 6.1 创建 Ticket ```http POST /auth/sso/vehicle-platform/tickets Authorization: Bearer Content-Type: application/json ``` 请求: ```json { "audience": "vehicle-data-platform", "redirectUri": "https://vehicle.example.com/auth/oneos/callback", "returnTo": "/vehicles", "requestId": "uuid" } ``` 成功响应: ```json { "code": 0, "data": { "ticket": "random-256-bit-value", "expiresIn": 60, "redirectUrl": "https://vehicle.example.com/auth/oneos/callback?ticket=..." }, "requestId": "uuid" } ``` 要求: - 只有已登录且具备 `vehicle:platform:access` 的用户可以创建; - Ticket 至少使用 256 位密码学随机数; - OneOS 只保存 Ticket 的 SHA-256; - 有效期建议 60 秒,最长不得超过 120 秒; - Ticket 只能成功消费一次; - Ticket 绑定 `audience`、用户、租户和回调地址; - `returnTo` 仅允许车辆中台站内白名单路径; - 对同一用户和 IP 限流; - 响应头 `Cache-Control: no-store`; - 日志不得记录 Ticket 原文。 ### 6.2 消费并解析 Ticket ```http POST /inner/v1/sso/vehicle-platform/introspect Authorization: Service X-Request-Id: X-Request-Timestamp: X-Request-Signature: Content-Type: application/json ``` 请求: ```json { "ticket": "random-256-bit-value", "audience": "vehicle-data-platform" } ``` 签名原文: ```text POST /inner/v1/sso/vehicle-platform/introspect ``` 成功响应: ```json { "code": 0, "data": { "active": true, "subject": "50001", "userId": "50001", "username": "zhangsan", "nickname": "张三", "tenantId": "000000", "departmentIds": ["40001"], "roleKeys": ["business_manager"], "permissions": [ "vehicle:platform:access", "vehicle:scope:department" ], "identityVersion": "user-50001-v18", "authenticatedAt": "2026-07-24T10:00:00+08:00", "expiresAt": "2026-07-24T10:05:00+08:00" }, "requestId": "uuid" } ``` 约束: - 所有雪花 ID 均使用 JSON 字符串; - introspection 必须原子消费 Ticket; - 重复消费返回统一失效错误; - 消费时重新检查用户状态和关键权限; - 不返回密码、手机号、身份证、RuoYi Token 和 Redis Key; - OneOS 拒绝超过 60 秒的时间戳、重复请求 ID、错误服务令牌、错误签名和错误来源网络; - 网关必须剥离外部传入的同名签名头; - OneOS SSO 与车辆业务快照使用不同服务令牌和签名密钥。 ### 6.3 错误码 | HTTP | code | 含义 | |---|---|---| | 400 | `SSO_REQUEST_INVALID` | 参数或回调地址无效 | | 401 | `SSO_LOGIN_REQUIRED` | RuoYi 登录失效 | | 403 | `SSO_ACCESS_DENIED` | 用户停用或无中台入口权限 | | 404 | `SSO_TICKET_INVALID` | Ticket 不存在、过期或已消费 | | 409 | `SSO_TICKET_REPLAYED` | Ticket 重放 | | 429 | `SSO_RATE_LIMITED` | 请求过多 | | 500 | `SSO_IDENTITY_UNAVAILABLE` | 无法读取权威用户信息 | | 503 | `SSO_SERVICE_UNAVAILABLE` | SSO 服务不可用 | 客户端不得根据不同 Ticket 错误推测用户是否存在。 ## 7. 车辆数据中台接口契约 ### 7.1 Ticket 交换 ```http POST /api/v2/auth/oneos/exchange Content-Type: application/json ``` 请求: ```json { "ticket": "...", "returnTo": "/vehicles" } ``` 成功响应保持与本地登录一致: ```json { "data": { "accessToken": "", "expiresAt": "2026-07-24T10:05:00+08:00", "returnTo": "/vehicles", "session": { "subjectId": "42", "name": "张三", "username": "zhangsan", "role": "customer", "userType": "customer", "authProvider": "OneOS", "menuKeys": ["vehicles"], "vehicleCount": 18, "businessScopeLevel": "department", "departmentIds": ["40001"] } } } ``` ### 7.2 中台交换处理 1. 校验请求体大小、Ticket 格式和站内 `returnTo`; 2. 使用独立服务身份调用 OneOS introspection; 3. 校验 `active`、`subject`、`expiresAt`、访问权限和必需 Scope 字段; 4. 以 `(auth_provider='OneOS', external_subject=subject)` 查找账号; 5. 按策略自动创建或更新中台客户账号; 6. 在同一数据库事务更新: - `platform_user`; - `platform_user_menu`; - `platform_user_business_scope`; - 身份同步审计; 7. 读取当前 OneOS 业务投影并计算 VIN; 8. Scope 计算异常时不创建会话; 9. 创建中台随机会话 Token,数据库只保存 SHA-256; 10. 返回中台 Session,不返回 OneOS Ticket 或 OneOS Token。 ### 7.3 会话策略 - OneOS 中台会话首期建议最长 5 分钟; - 前端可在会话即将到期时重新走静默 Ticket 流程; - 中台主体缓存最长 30 秒; - OneOS 身份版本变化后,新 exchange 立即生效; - OneOS 用户停用最迟在当前 5 分钟会话结束时生效; - 如要求近实时停用,可增加 OneOS 会话撤销通知或每 30 秒 introspection; - 退出中台只撤销中台会话,不必退出 OneOS; - OneOS 全局退出后不得继续签发新 Ticket。 ## 8. 数据映射与数据库计划 ### 8.1 复用表 ```text platform_user platform_user_menu platform_user_session platform_user_business_scope business_scope_state business_customer_vehicle_scope platform_auth_audit ``` ### 8.2 建议新增身份同步审计表 ```text platform_external_identity_sync_audit id auth_provider external_subject identity_version scope_level department_ids responsible_user_id result reason_code trace_id created_at ``` 安全要求: - 不保存 Ticket、OneOS Token、服务密钥; - 审计中的用户 ID 可保存,VIN 只在必要时保存摘要; - `department_ids` 标准化、去重和限长; - 账号和业务 Scope 更新必须事务化; - OneOS 已映射账号不存在时,默认策略必须明确选择: - 推荐:允许受控 JIT 自动创建 `customer`; - 更严格:管理员预先创建,未知身份拒绝。 ## 9. OneOS AI(Codex)开发职责 ### 9.1 代码范围 允许修改: - `ruoyi-auth`; - `ruoyi-gateway` 路由和内部接口安全配置; - 必需的公共 DTO、安全组件和测试; - OneOS 前端车辆中台菜单跳转逻辑; - SSO Ticket 专用数据库表或 Redis Key; - SSO 运维配置和文档。 禁止修改: - `ln_asset_management` 车辆、合同、交还车业务判断; - 业务负责人和部门的现有权威数据语义; - 车辆数据中台代码; - 通过前端拼接用户信息替代服务端认证。 ### 9.2 工作包 O-1:RuoYi 版本与身份字段确认 交付: - RuoYi 分支、Spring Boot 版本和认证组件说明; - 当前 Token Header、前缀和失效机制; - `LoginUser` 可稳定取得的字段; - `userId → responsible_user_id` 一致性结论; - 部门负责人角色/权限编码; - 测试账号清单。 完成标准: - 不依赖姓名匹配; - 明确单部门或多部门; - 明确停用用户的判定字段。 ### 9.3 工作包 O-2:权限编码与菜单入口 实现: - 新增或确认 `vehicle:platform:access`; - 新增或确认 `vehicle:scope:department`; - 配置部门负责人和普通业务人员; - OneOS 菜单只对具备入口权限的用户显示; - 菜单点击前调用创建 Ticket 接口。 测试: - 无权限用户不可见且接口返回 403; - 普通业务人员不会获得部门级权限; - OneOS 管理员不会自动获得中台管理员权限。 ### 9.4 工作包 O-3:Ticket 创建 实现: - 当前 RuoYi Token 验证; - Ticket 密码学随机生成; - Ticket 哈希存储、TTL、绑定字段; - 单用户/IP 限流; - 回调地址白名单; - `no-store` 和敏感日志清理。 测试: - 未登录、停用、无权限、错误回调、过量请求; - Ticket 长度、唯一性和到期; - 日志中不存在 Ticket 原文。 ### 9.5 工作包 O-4:Introspection 实现: - 服务令牌; - HMAC-SHA256; - 时间戳窗口; - 请求 ID 防重放; - 来源网络限制; - Ticket 原子消费; - 用户状态和权限二次校验; - 最小身份响应。 测试: - 错误服务令牌、签名、时间戳和请求 ID; - Ticket 首次成功、第二次失败; - Ticket 到期; - 用户创建 Ticket 后被停用; - 用户权限在创建和消费之间被移除; - 并发消费只有一个成功。 ### 9.6 工作包 O-5:可观测性和部署 实现: - Ticket 创建/消费成功率; - 错误码计数; - 延迟; - 重放和签名失败告警; - 配置密钥轮换说明; - 灰度开关; - 回滚开关。 不得在指标和日志中记录 Ticket、OneOS Token 或签名密钥。 ### 9.7 OneOS AI 最终交付物 - 接口实现; - OpenAPI/接口文档; - 字段样例和错误码; - 自动化测试报告; - 测试环境地址; - 服务 Token 和签名密钥的安全交付方式; - 回调地址白名单配置; - 两类测试账号; - 部署、回滚和密钥轮换说明。 ## 10. 车辆数据中台 AI(Codex)开发职责 ### 10.1 代码范围 允许修改: - `apps/api/internal/app` 鉴权和会话; - `apps/api/internal/config` SSO 配置; - `apps/api/internal/platform` Principal 和业务 Scope; - `apps/web/src/v2/auth` 回调和会话恢复; - 中台数据库迁移; - 中台部署配置、测试和文档。 禁止修改: - OneOS/RuoYi 源码; - OneOS Redis 和业务数据库; - OneOS 角色或部门事实; - 通过直接查询 `ln_asset_management` 判断用户登录态。 ### 10.2 工作包 V-1:配置和 OneOS 客户端 新增配置: ```text ONEOS_SSO_ENABLED=false ONEOS_SSO_INTROSPECTION_URL= ONEOS_SSO_SERVICE_TOKEN= ONEOS_SSO_SIGNING_SECRET= ONEOS_SSO_AUDIENCE=vehicle-platform ONEOS_SSO_DEFAULT_MENUS=vehicles ONEOS_SSO_REQUEST_TIMEOUT_MS=3000 ONEOS_SSO_SESSION_TTL_MINUTES=30 ``` 实现: - 有界 HTTP 客户端; - 独立超时; - 请求 ID、时间戳和 HMAC; - 结构化错误; - 429/5xx 有界重试; - 4xx 不重试; - 响应大小限制; - 密钥不进入日志。 ### 10.3 工作包 V-2:IdentityAdapter 实现具体 `OneOSIdentityAdapter`: - 调用 introspection; - 校验响应字段; - 标准化 ID; - 校验 `active` 和 `expiresAt`; - 将 OneOS 权限映射为中台 Scope; - 禁止映射中台管理员; - 输出统一强类型 Principal 输入。 ### 10.4 工作包 V-3:账号和 Scope 事务同步 实现: - 以外部主体唯一键查询; - JIT 创建或更新客户账号; - 维护 `auth_provider='OneOS'`; - 更新菜单权限; - 更新 `platform_user_business_scope`; - 记录身份版本和审计; - 权限降级时立即清除旧 Scope; - 缺失字段失败关闭。 ### 10.5 工作包 V-4:交换接口和中台会话 实现: - `POST /api/v2/auth/oneos/exchange`; - 允许该接口在未登录状态访问,但必须有严格限流; - 创建中台随机会话; - OneOS 会话 TTL 独立设置; - 响应与现有本地登录保持兼容; - 登录成功、失败和 Scope 结果进入审计; - 交换成功后清理同一外部账号的过期会话。 ### 10.6 工作包 V-5:前端回调 实现路由: ```text /auth/oneos/callback ``` 行为: - 读取 Ticket 后立即从地址栏清除; - 调用 exchange; - 保存中台 Access Token; - 清空上一账号 React Query 缓存; - 获取 `/api/v2/session`; - 跳转到白名单 `returnTo`; - 显示安全的加载、失败和重试界面; - 不把 Ticket 写入本地存储、日志和错误上报; - 保留本地账号登录作为回滚入口。 ### 10.7 工作包 V-6:权限回归 覆盖: - 车辆查询和详情; - 实时监控和地图; - 轨迹; - 历史数据和 RAW; - 里程统计; - 导出; - 告警和异步任务; - 业务筛选候选项。 必须证明 Query、Body 和普通 Header 不能扩大 VIN Scope。 ### 10.8 工作包 V-7:运维与发布 实现: - SSO 功能开关; - SSO 成功率和延迟; - OneOS 调用错误码; - 登录、Scope 和拒绝审计; - 服务密钥轮换; - 灰度账号/部门白名单; - 保留本地管理员和应急 Token; - 故障时关闭 SSO,不开放全量车辆。 ### 10.9 车辆数据中台 AI 最终交付物 - OneOS SSO 客户端和适配器; - exchange API; - 前端回调页; - 数据库迁移; - 单元、集成、端到端和越权测试; - 运维配置模板; - 监控和审计说明; - 发布、灰度和回滚手册。 ## 11. 双方协作与交付顺序 | 阶段 | OneOS AI | 中台 AI | 退出条件 | |---|---|---|---| | P0 契约确认 | 字段、角色、版本确认 | Scope 和会话策略确认 | 契约冻结 | | P1 Mock 联调 | 提供固定 introspection Mock | 完成客户端和 Adapter | 契约测试通过 | | P2 OneOS 开发 | Ticket + introspection | exchange + 回调页 | 双方单测通过 | | P3 测试环境 | 部署 OneOS 测试接口 | 部署中台 SSO 开关 | 两类账号可登录 | | P4 权限验收 | 提供跨部门样本 | 全 API 越权测试 | 零越权 | | P5 灰度 | 仅开放灰度用户 | 仅启用灰度白名单 | 运行 3 个工作日 | | P6 正式发布 | 全量启用菜单 | 启用 SSO 入口 | 指标稳定 | 依赖关系: 1. OneOS 先交付字段和 Mock; 2. 中台按冻结契约完成客户端; 3. OneOS 再交付真实接口; 4. 双方测试环境联调; 5. 完成权限验收后才能灰度; 6. 灰度期间不得关闭本地登录和应急入口。 ## 12. Codex 任务交接格式 双方 Codex 每次交接必须提供: ```text 任务编号: 代码仓库与分支: 提交 SHA: 接口版本: 配置变更: 数据库迁移: 测试命令与结果: 已知限制: 联调地址: 需要对方确认的字段: 回滚方式: ``` 接口字段发生变化时: 1. 先更新契约; 2. 提供兼容期; 3. 双方契约测试同时支持新旧版本; 4. 不允许一方静默修改字段语义; 5. 雪花 ID 类型从字符串改为数字视为破坏性变更。 ## 13. 测试与验收矩阵 ### 13.1 功能用例 1. OneOS 已登录用户点击菜单,无需再次输入密码; 2. 部门级负责人看到本部门全部业务车辆; 3. 普通业务人员只看到本人负责车辆; 4. 多部门负责人只看到声明的部门; 5. 四类车辆业务筛选在授权范围内正常工作; 6. 中台刷新后会话可恢复; 7. 中台退出后可重新从 OneOS 进入; 8. 本地管理员登录不受影响。 ### 13.2 安全用例 1. 修改 `deptId/userId/role` Query 无效; 2. 伪造普通身份头无效; 3. Ticket 过期失败; 4. Ticket 重放失败; 5. Ticket 并发消费只有一个成功; 6. HMAC 错误失败; 7. 时间戳过期失败; 8. 请求 ID 重放失败; 9. 错误 audience 失败; 10. 用户停用失败; 11. 用户无入口权限失败; 12. 普通用户伪装部门负责人失败; 13. 客户端业务筛选不能扩大 Principal VIN Scope; 14. OneOS 不可用时不回退为全量; 15. 日志、指标、前端存储中无 Ticket 和 OneOS Token。 ### 13.3 数据一致性用例 1. `userId` 与 `responsible_user_id` 精确匹配; 2. 部门 ID 与业务投影 `department_id` 精确匹配; 3. 业务快照切换后新会话使用新范围; 4. 用户从部门负责人降级后不保留旧部门 Scope; 5. 用户调部门后不保留旧部门车辆; 6. Scope 为空返回零车辆; 7. 业务投影不可用时拒绝业务身份登录或数据访问。 ### 13.4 性能目标 - Ticket 创建 P95 小于 200 ms; - introspection P95 小于 300 ms; - 中台 exchange P95 小于 800 ms; - 登录全链路 P95 小于 2 秒; - 单 Ticket 仅一次 OneOS introspection; - 车辆 Scope 计算不得产生按车辆 N+1 查询; - SSO 故障不得拖垮车辆查询线程池。 ## 14. 灰度、监控与告警 ### 14.1 灰度顺序 1. 一个普通业务人员; 2. 一个部门级负责人; 3. 一个包含多客户和多运营状态的部门; 4. 10% 业务用户; 5. 全量业务用户。 ### 14.2 核心指标 - Ticket 创建数、成功率、拒绝率; - introspection 成功率、重放数、签名失败数; - exchange 成功率和阶段耗时; - JIT 创建/更新账号数; - department/responsible Scope 用户数; - 零车辆会话数; - 权限拒绝数; - OneOS 调用超时和 5xx; - 会话失效和重新登录次数。 ### 14.3 告警 - 5 分钟内 SSO 成功率低于 95%; - 签名失败或重放出现; - 零车辆会话数量突增; - department Scope 车辆数量异常增长; - OneOS 用户停用但中台仍成功创建会话; - 业务投影超过允许陈旧时间; - 同一外部主体映射多个中台账号。 ## 15. 发布与回滚 ### 15.1 发布前 - 契约冻结; - 双方自动化测试通过; - 密钥通过安全渠道配置; - 回调域名和内网白名单完成; - 数据库迁移完成; - 本地管理员和应急 Token 验证; - 灰度开关默认关闭; - 监控和告警已部署。 ### 15.2 回滚 OneOS 回滚: - 隐藏车辆中台菜单; - 关闭 Ticket 签发; - 保留接口日志和指标; - 不影响 OneOS 原有登录。 中台回滚: - `ONEOS_SSO_ENABLED=false`; - 停止接受新的 OneOS exchange; - 撤销现有 OneOS 中台会话; - 保留本地账号和应急 Token; - 不删除身份映射和审计; - 绝不把 OneOS 用户降级为无 Scope 全量账号。 ## 16. 评审前待确认项 OneOS 团队必须回答: 1. 是标准 RuoYi-Cloud、RuoYi-Cloud-Plus 还是二次认证实现? 2. 当前分支、Spring Boot 版本和 TokenService 实现位置? 3. `userId` 是否等于业务投影 `responsible_user_id`? 4. 用户是否只有一个 `deptId`? 5. 哪个稳定权限编码代表部门全部车辆权限? 6. 是否接受增加两个 `/inner/v1/sso` 接口? 7. Ticket 存 Redis 还是专用数据库表? 8. OneOS 测试环境、网关地址和网络白名单是什么? 9. 是否存在统一登出或账号停用通知需求? 10. 生产回调域名是什么? 车辆中台团队必须回答: 1. JIT 自动创建还是管理员预创建? 2. OneOS 用户默认开放哪些中台菜单? 3. 5 分钟会话 TTL 是否满足停用时效? 4. 是否需要多部门 Scope? 5. 业务投影最大允许陈旧时间是多少? 6. 灰度用户和部门名单是什么? ## 17. 双方 Codex 首轮任务指令 ### 17.1 发给 OneOS AI(Codex) ```text 请在 OneOS RuoYi-Cloud 仓库中先完成只读调研,不修改 ln_asset_management 业务逻辑。 目标: 1. 确认 RuoYi 分支、Spring Boot 版本、TokenController、TokenService、LoginUser 和 Gateway 鉴权链路; 2. 确认 sys_user.user_id、dept_id、角色 key、权限字符串、用户状态字段; 3. 核对 sys_user.user_id 是否与车辆业务关系 responsible_user_id 一致; 4. 设计并实现: POST /auth/sso/vehicle-platform/tickets POST /inner/v1/sso/vehicle-platform/introspect 5. 使用当前 RuoYi 登录态创建 60 秒单次 Ticket; 6. introspection 使用独立 Service Token、HMAC、时间戳和 Request ID 防重放; 7. 返回最小身份字段,不返回 OneOS Token、密码、手机号和 Redis Key; 8. 增加并发单次消费、过期、停用、权限移除、签名和重放测试; 9. 提供接口契约、测试命令、配置项、回滚方式和提交 SHA。 禁止: - URL 传 OneOS Token; - 共享 Redis/JWT Secret; - 信任浏览器 userId/deptId/role; - 修改车辆、合同、交还车业务逻辑。 ``` ### 17.2 车辆数据中台 AI(Codex)首轮任务 ```text 在车辆数据中台实现 OneOS RuoYi-Cloud SSO 接入。 目标: 1. 新增 OneOS SSO 配置和有界 introspection 客户端; 2. 实现 OneOSIdentityAdapter; 3. 新增 POST /api/v2/auth/oneos/exchange; 4. 以 (OneOS, subject) 映射 platform_user; 5. 按 vehicle:scope:department 映射 department Scope,否则映射 responsible Scope; 6. 事务更新账号、菜单、platform_user_business_scope 和审计; 7. 创建最长 5 分钟的中台会话; 8. 新增 /auth/oneos/callback,Ticket 只在内存中使用并立即从 URL 清除; 9. 覆盖普通用户、部门负责人、停用、重放、过期、错误签名和全 API 越权测试; 10. 保留本地登录和应急 Token,SSO 异常时失败关闭。 在 OneOS 正式接口未交付前,先使用契约 Mock 开发,不伪造生产用户信息。 ``` ## 18. 参考 - RuoYi-Cloud 官方认证中心说明: - RuoYi-Cloud 官方 `TokenController`: - RuoYi-Cloud 官方 `TokenService`: - 中台业务范围契约:`docs/oneos-customer-vehicle-scope-contract.md` - 中台鉴权说明:`docs/authentication-authorization.md` - 中台 OneOS 用户 Scope 迁移:`deploy/migrations/039_oneos_business_user_scope.sql`