Files
lingniu-vehicle-ingest/vehicle-data-platform/docs/oneos-ruoyi-cloud-sso-integration-plan.md
2026-07-27 16:46:15 +08:00

923 lines
28 KiB
Markdown
Raw 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.
# OneOSRuoYi-Cloud与车辆数据中台统一登录及业务权限集成方案
更新时间2026-07-24
状态:首期代码已完成,待部署配置与测试环境端到端验收
责任团队OneOS AICodex、车辆数据中台 AICodex
## 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 <current-ruoyi-token>
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 <service-token>
X-Request-Id: <uuid>
X-Request-Timestamp: <unix-seconds>
X-Request-Signature: <hmac-sha256>
Content-Type: application/json
```
请求:
```json
{
"ticket": "random-256-bit-value",
"audience": "vehicle-data-platform"
}
```
签名原文:
```text
POST
/inner/v1/sso/vehicle-platform/introspect
<unix-seconds>
<request-id>
<sha256-lower-hex-of-body>
```
成功响应:
```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": "<platform-session-token>",
"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 AICodex开发职责
### 9.1 代码范围
允许修改:
- `ruoyi-auth`
- `ruoyi-gateway` 路由和内部接口安全配置;
- 必需的公共 DTO、安全组件和测试
- OneOS 前端车辆中台菜单跳转逻辑;
- SSO Ticket 专用数据库表或 Redis Key
- SSO 运维配置和文档。
禁止修改:
- `ln_asset_management` 车辆、合同、交还车业务判断;
- 业务负责人和部门的现有权威数据语义;
- 车辆数据中台代码;
- 通过前端拼接用户信息替代服务端认证。
### 9.2 工作包 O-1RuoYi 版本与身份字段确认
交付:
- 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-3Ticket 创建
实现:
- 当前 RuoYi Token 验证;
- Ticket 密码学随机生成;
- Ticket 哈希存储、TTL、绑定字段
- 单用户/IP 限流;
- 回调地址白名单;
- `no-store` 和敏感日志清理。
测试:
- 未登录、停用、无权限、错误回调、过量请求;
- Ticket 长度、唯一性和到期;
- 日志中不存在 Ticket 原文。
### 9.5 工作包 O-4Introspection
实现:
- 服务令牌;
- HMAC-SHA256
- 时间戳窗口;
- 请求 ID 防重放;
- 来源网络限制;
- Ticket 原子消费;
- 用户状态和权限二次校验;
- 最小身份响应。
测试:
- 错误服务令牌、签名、时间戳和请求 ID
- Ticket 首次成功、第二次失败;
- Ticket 到期;
- 用户创建 Ticket 后被停用;
- 用户权限在创建和消费之间被移除;
- 并发消费只有一个成功。
### 9.6 工作包 O-5可观测性和部署
实现:
- Ticket 创建/消费成功率;
- 错误码计数;
- 延迟;
- 重放和签名失败告警;
- 配置密钥轮换说明;
- 灰度开关;
- 回滚开关。
不得在指标和日志中记录 Ticket、OneOS Token 或签名密钥。
### 9.7 OneOS AI 最终交付物
- 接口实现;
- OpenAPI/接口文档;
- 字段样例和错误码;
- 自动化测试报告;
- 测试环境地址;
- 服务 Token 和签名密钥的安全交付方式;
- 回调地址白名单配置;
- 两类测试账号;
- 部署、回滚和密钥轮换说明。
## 10. 车辆数据中台 AICodex开发职责
### 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-2IdentityAdapter
实现具体 `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 AICodex
```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 车辆数据中台 AICodex首轮任务
```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/callbackTicket 只在内存中使用并立即从 URL 清除;
9. 覆盖普通用户、部门负责人、停用、重放、过期、错误签名和全 API 越权测试;
10. 保留本地登录和应急 TokenSSO 异常时失败关闭。
在 OneOS 正式接口未交付前,先使用契约 Mock 开发,不伪造生产用户信息。
```
## 18. 参考
- RuoYi-Cloud 官方认证中心说明:<https://doc.ruoyi.vip/ruoyi-cloud/cloud/auth.html>
- RuoYi-Cloud 官方 `TokenController`<https://gitee.com/y_project/RuoYi-Cloud/blob/springboot3/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java>
- RuoYi-Cloud 官方 `TokenService`<https://gitee.com/y_project/RuoYi-Cloud/blob/master/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java>
- 中台业务范围契约:`docs/oneos-customer-vehicle-scope-contract.md`
- 中台鉴权说明:`docs/authentication-authorization.md`
- 中台 OneOS 用户 Scope 迁移:`deploy/migrations/039_oneos_business_user_scope.sql`