10 KiB
OneOS 客户车辆门户变更审批提案
更新时间:2026-07-14
状态:已停止。2026-07-14 用户明确要求不修改 ln-asset-management 任何逻辑;此前本地试验改动已全部撤销,OneOS 仓库保持干净。本文件仅保留为风险证据,不构成待执行审批项。
1. 审批目标
本提案只解决客户只读访问车辆数据所必需的三件事:
- OneOS 能稳定识别客户账号并输出不可伪造的客户身份;
- OneOS 的“当前客户车辆”事实不会因合同保存被破坏;
- 车辆数据中台收到客户身份后,只能访问该客户的车辆 Scope。
车辆锁车、控车以及保险、结算、事故、违章等客户功能不在本批次范围内。
2. 当前源码证据
2.1 客户车辆 RPC 当前会泄露全量车辆
ln-asset-management/src/main/java/com/ln/asset/api/impl/RemoteVehicleServiceImpl.java:83
的 listByCustomerId 忽略 customerId,实际只按 del_flag=0 查询。其 VO 转换也没有回填
customerId 和 contractCode。
该接口在修复前必须保持内部禁用,不能作为车辆数据中台的授权来源。
2.2 当前租赁 Mapper 会丢字段
ln-asset-management/src/main/resources/mapper/VehicleLeaseOrderRecordMapper.xml:6
的 BaseResultMap 与 Base_Column_List 缺少以下实体字段:
customer_id、project_name;delivery_vehicle_id、last_delivery_name;return_vehicle_task_id、last_return_name;update_by。
使用这些自定义查询取得记录后,上述字段会变成空值。生产审计同时发现聚合记录与最新历史记录有 325 条关键字段差异,不能把空值当成“无业务关系”。
2.3 合同保存会清空交还车事实
VehicleLeaseOrderRecordServiceImpl.java:262 在 deliveryVehicleId == null 时,同时清空交车和还车的
单据 ID、时间、里程与操作人。合同提交/更新并不代表交车事实撤销,因此这里违反业务事实的单一写入原则。
交车字段只能由交车完成/撤销流程修改;还车字段只能由还车完成/撤销流程修改。合同更新只能更新客户、合同、 项目和业务组织字段。
2.4 客户账号当前不能安全登录
CustomerInfoServiceImpl.java:188先尝试创建sys_user,之后才保存客户档案;远程调用失败被吞掉,两个库之间不存在事务一致性。SysUserRegistrar.java:27给所有业务账号使用共享初始密码ln123456。RemoteUserServiceImpl.java:222把业务账号开通绑定到公开注册开关sys.account.registerUser。UserType.java:14只支持sys_user和app_user;customer会在 Sa-Token 权限解析时抛异常。- 密码登录按
tenantId + username查询,短信登录默认取同手机号的第一条记录,均不能可靠区分客户账号。 - 更新客户档案不会同步账号;删除客户时账号删除异常同样只记日志。
生产审计结果是 335 个有效客户中,当前客户账号数量为 0,因此不能直接批量启用现有逻辑。
3. 推荐变更批次
B1:修复客户车辆业务事实(ln-asset-management)
预计修改文件:
src/main/resources/mapper/VehicleLeaseOrderRecordMapper.xmlsrc/main/java/com/ln/asset/modules/contract/mapper/VehicleLeaseOrderRecordMapper.javasrc/main/java/com/ln/asset/modules/contract/service/impl/VehicleLeaseOrderRecordServiceImpl.javasrc/main/java/com/ln/asset/api/impl/RemoteVehicleServiceImpl.javaln-asset-api/src/main/java/com/ln/asset/api/RemoteVehicleService.javaln-asset-api/src/main/java/com/ln/asset/api/domain/vo/RemoteVehicleVo.java- 对应单元/集成测试文件
变更内容:
- 补齐 Mapper 的所有实体字段映射与列清单;禁止“读出空值再全实体更新”覆盖已有事实。
- 把合同字段更新与交车/还车生命周期更新拆开:合同保存不再修改任何交还车字段。
- 增加显式的当前 Scope 查询,条件必须同时包含有效车辆、有效客户、有效合同、已交车未还车、
record.customer_id = COALESCE(contract.other_customer_id, contract.customer_id)。 - 异常关系返回隔离原因,不为其生成授权记录。
- 修复
listByCustomerId,但将其标注为兼容接口;车辆中台继续使用已实现的最小权限 RDS 快照同步, 不依赖一次 RPC 返回无限列表。 - 交车、还车聚合更新失败必须让业务事务失败或写入可重试 Outbox,不能仅记录日志后继续成功。
明确不做:
- 不把遥测位置、在线状态或总里程回写为交还车业务事实;
- 不恢复
vehicle_info.customer_id作为客户归属; - 不修改锁车、控车业务。
验收测试:
- 客户 A 查询结果不含客户 B 车辆;空客户 ID 返回空集合;
- 丙方客户存在时只归属
other_customer_id; - 未交车、已还车、客户/合同不一致、缺 VIN 的车辆均不授权;
- 合同重复保存前后,交还车单 ID、时间、里程完全不变;
- 同一车辆存在多个当前关系时整体隔离,而不是任选一条;
- 本段验收基线已被事务事实影子查询取代;当前只读中台口径为 639 个候选、613 个可发布、26 个隔离。
回滚:
- B1 不删除字段、不改变 Dubbo 方法签名;可按服务版本回滚;
- 新查询与旧接口并存一个版本,车辆中台只读同步可独立停用;
- 数据修复 SQL 与代码发布分开审批,禁止发布脚本自动改写异常关系。
B2:建立客户账号一致性(ln-cloud + ln-asset-management)
预计修改文件/模块:
ln-cloud/ruoyi-common/ruoyi-common-core/.../UserType.javaln-cloud/ruoyi-common/ruoyi-common-satoken/.../SaPermissionImpl.javaln-cloud/ruoyi-api/ruoyi-api-system/.../RemoteUserService.javaln-cloud/ruoyi-modules/ruoyi-system/.../RemoteUserServiceImpl.javaln-cloud/ruoyi-modules/ruoyi-system/.../ISysUserService.javaln-cloud/ruoyi-modules/ruoyi-system/.../SysUserServiceImpl.javaln-cloud/ruoyi-auth新增独立客户认证策略ln-asset-management客户账号开通、更新、停用 Outbox/补偿任务- 新增账号绑定/激活所需数据库迁移与测试
变更内容:
- 增加明确的
CUSTOMER("customer")类型,并为客户主体返回固定、最小的门户权限,不继承后台菜单权限。 - 新增内部“业务账号开通”接口,不再复用公开自助注册开关;接口以
(tenantId, userType, businessId)幂等,并校验用户名、手机号冲突。 - 增加显式业务绑定,不能仅依赖
sys_user.user_id == customer_info.id的偶然约定。 - 客户档案事务写入 Outbox;账号、角色、绑定创建失败可重试、可告警、可人工补偿。前端明确展示“账号待开通”, 不再静默成功。
- 删除共享默认密码。采用一次性随机激活凭证,短时有效、单次使用;激活后立即失效。
- 新增独立
customer_password/customer_sms登录策略。客户类型由受信客户端配置或策略固定,不能由浏览器 任意传入;后台密码登录仍只允许后台账号。 - 客户停用、删除或合作终止时撤销其会话,并产生身份版本变更事件。
- 存量补偿先输出冲突清单;335 个客户不得按手机号自动合并,审计发现的 4 个手机号匹配必须人工确认。
验收测试:
- 同用户名/手机号存在不同主体类型时,客户登录只能命中 customer;
- 客户账号不能使用后台登录策略,后台账号不能使用客户策略;
- 公开注册关闭时,内部业务账号开通仍可按授权调用;
- 重复 Outbox 消息不会创建重复账号、绑定或角色;
- 激活凭证不能复用,日志中不出现明文凭证或密码;
- 删除/停用客户后现有 token 立即失效;
- 客户权限解析不抛
UserType not found,且没有后台菜单权限。
回滚:
- 新客户认证使用独立 grant type 和独立客户端,关闭该客户端即可停止入口;
- 绑定表和 Outbox 只新增,不破坏现有后台账号;
- 回滚应用版本前先停止补偿消费者,不删除已经创建的客户账号,只统一停用,避免 ID 被复用。
B3:向车辆中台签发短时身份(ln-cloud/ruoyi-auth)
推荐新增内部/登录后交换接口:
POST /inner/v1/vehicle-platform/token
Authorization: Bearer <oneos-customer-token>
服务端从 Sa-Token 会话和业务绑定取得 userId/customerId/tenantId/userType,签发最长 5 分钟、
aud=vehicle-data-platform 的短时 JWT。浏览器不能提交或覆盖 customerId。
最低声明:
{
"iss": "oneos-auth",
"aud": "vehicle-data-platform",
"sub": "<sys_user.user_id>",
"subjectType": "customer",
"customerId": "<customer_info.id>",
"tenantId": "<tenant_id>",
"scope": ["vehicle:read"],
"identityVersion": 1,
"iat": 0,
"exp": 0,
"jti": "<random>"
}
安全要求:
- 使用非对称签名,车辆中台只持有公钥;密钥 ID 支持轮换;
- 严格校验发行方、受众、算法、
exp/nbf/iat、主体类型和客户 ID; - 网关删除外部传入的同名身份头;不信任
X-Customer-Id; - Scope 投影过期、身份绑定缺失或账号停用时,车辆中台失败关闭;
- 任何越权详情统一返回 404,避免泄露 VIN 或告警 ID 是否存在。
回滚:停止 token 交换接口或撤销对应客户端;车辆中台客户入口关闭,内部管理员入口不受影响。
4. 数据库变更必须单独审批
在修复 1 组重复聚合记录并确认软删除语义前,不直接添加唯一约束。建议顺序:
- 输出重复记录和 26 条隔离关系的业务核对清单;
- 由合同/交还车业务负责人确认每条修复方式;
- 在预发布库回放合同保存、交车、还车、再次交车和丙方客户用例;
- 再评估
vehicle_lease_order_record(vehicle_id)唯一约束及 Scope 查询索引; - DDL 使用在线方式并准备反向 DDL,不与应用代码在同一步骤自动执行。
5. 推荐审批顺序
- B1/B2 已停止,不修改 OneOS 业务逻辑;
- 先完成车辆中台只读 Scope 投影与异常隔离;
- 客户身份入口需另行确定可信身份来源并通过双客户越权测试;
- 最后才进行外部客户灰度。
每个批次独立提交、独立发布、独立回滚。未经用户明确同意,不修改上述 OneOS 文件。