# 08 敏感数据合规、凭据安全与门禁审计体系 (Security and Audit) > **安全最高红线**:智能门锁直接关联学员人身财产安全与公寓物理边界防线。 > **设计原则**:**最小知悉原则、凭据零明文长期留存、全链路日志脱敏、关键动作两票制双人审计轨迹**。 --- ## 1. 门禁凭据类型全面比选与首期试点推荐 ### 1.1 四类门锁开门凭据深度对比矩阵 | 评估维度 | 在线临时密码 (Online Password) | 在线实体学员卡 (Online Card) | 离线算法密码 (Offline Password) | 远程网络开锁 (Remote Unlock) | | :--- | :--- | :--- | :--- | :--- | | **实施复杂度** | **低**(纯软件 API 交互) | **中**(需发卡设备与现场制卡) | 高(需手工向学员通知长串数字) | 低(API 触发) | | **硬件与耗材依赖** | **零硬件依赖**(手机/短信/凭条) | **依赖物理卡片**及 USB 读写卡器 | 零硬件依赖 | 依赖集中网关长连接 | | **是否需要学员手机号** | 是(DMS 接口要求 `phoneNumber`) | 否(仅需卡号十六进制) | 否 | 否 | | **支持精准有效期** | **支持**(毫秒级 `validStart/Until`) | **支持**(毫秒级 `validStart/Until`) | 仅支持固定颗粒度(如天/时) | 一次性即时脉冲触发 | | **远程主动撤权能力** | **强**(可随时调用 delete 接口撤销) | **强**(可随时调用 delete 接口撤销) | **极弱**(撤权需在锁上输入清空码) | 不适用 | | **门锁开门审计追溯** | **强**(记录包含持有人与密码标识) | **强**(记录包含卡号与持有人) | 弱(无法区分具体使用者身份) | 强(记录远程操作日志) | | **离线网络容灾能力** | 弱(下发与撤销时门锁必须在线) | 弱(下发与撤销时门锁必须在线) | **极强**(门锁离线依然可验证算法) | 无(断网完全无法执行) | | **现场运维与损耗成本** | **零损耗成本** | 存在卡片丢失、补卡、消磁运维成本 | 需人工现场解决锁具失步问题 | 零物理成本,但安全风险极高 | ### 1.2 首期接入推荐结论 (`RECOMMENDED_PILOT_CREDENTIAL`) - **【首推试点方案】在线限时密码 (Online Password)**: - **采纳理由**:零硬件附加成本;无需采购现场读写发卡器;完全通过软件 API 自动派发与注销;天然支持培训期间精准起止时间;开门流水完整可溯。 - **【备选方案】在线实体卡 (Online Card)**: - 若沈阳房建公寓段已统一配发带有芯片的学员出入证/铁路一卡通,可作为二阶段或并行备选,需配备发卡器及编码转换组件。 - **【其他方案评估】离线密码与二维码钥匙**: - 离线密码缺乏主动撤销能力,一期明确排除 (`OUT_OF_SCOPE`)。 - 二维码/手机钥匙虽在官方文档中存在明确端点 (`POST /rest/doorlock/qrcode/create` 与 `POST /rest/qrcode/delete`),分类为 `DOCUMENTED`,但返回体存在字段污染且无二维码具体载荷内容,其实际钥匙方案可行性归为 `NEEDS_BUSINESS_CONFIRMATION`,一期不作为首选试点方案。 --- ## 2. 在线实体卡卡号编码规约与 `CardNumberCodec` 设计 官方文档对在线卡片(`POST /rest/doorlock/online-card/create`)的卡号规定了非常特殊的**小端字节序十六进制转换规则**: ```mermaid flowchart TD Step1["读卡器读取 10 进制原始卡号"] -->|"例: 3161082660"| Step2["转成标准 16 进制大端串"] Step2 -->|"例: BC 6A 4B 24"| Step3["不足 8 位时高位补零"] Step3 -->|"例: 09 99 ED 24"| Step4["低位在前的字节序逆序转换 (Little-Endian)"] Step4 -->|"例: 24 4B 6A BC 或 24 ED 99 09"| Step5["送入 DMS API 的 cardNumber 参数"] ``` ### 2.1 架构封装纪律 - **严禁**在 Controller 或前端编写卡号翻转逻辑。 - 必须在 `com.ruoyi.train.integration.dms.util` 包中独立封装 `CardNumberCodec` 工具类,包含严格的正则表达式校验与单测用例覆盖(大端转小端、奇数位补零、10进制溢出校验)。 --- ## 3. 敏感数据存储与展示安全策略 ### 3.1 开门临时密码保护规范 - **密码长度规范与零明文落库**: - DMS 原生支持 4~8 位数字密码,系统 Pilot 建议生成 6 位限时密码。如果必须在数据库留存备查,必须采用 **AES-256-GCM** 对称加密存储(密钥由配置中心安全注入),严禁裸明文入库。 - **学员端展示规范**: - 学员在移动端或大屏查看门禁密码时,默认采用脱敏掩码(如 `****34`)。 - 支持【点击查看】一次性展示:需经过二次验证,明文仅在内存中暂存并在 30 秒后自动模糊遮挡。 ### 3.2 日志全局脱敏规则 (`Log Redaction`) 在系统的 Logback、HttpTrace 日志切面及审计日志中,必须对以下字段强制执行脱敏: - `password` / `fuzzyPassword`:统一脱敏为 `******`。 - `appsecret` / `token`:绝对禁止打印,统一替换为 `[REDACTED_SECRET]`。 - `phoneNumber`:国内手机号统一脱敏为 `189****0952`。 - `cardNumber`:卡号中间 4 位脱敏。 --- ## 4. 远程开锁高风险主动控制规约 (`Remote Unlock Risk`) `POST /rest/doorlock/remote-unlock` 属于**最高风险的主动物理控制操作**。一旦滥用或被恶意调用,将直接打开学员宿舍房门。 ### 4.1 控制红线要求 1. **一期范围判定**: - **默认不在一期学员与常规宿管界面开放**,标记为 `P2_FUTURE / 受控应急`。 2. **安全防护机制(若未来业务强制启用)**: - **专属高危权限标识**:定义为 `train:access:remoteUnlock`。 - **角色范围限定**:仅限系统超级管理员或经段保卫科书面授权的当值值班长使用。严禁授予任课教师 (`Teacher`) 或学员 (`Student`)。 - **二次身份确认**:界面弹出高危告警弹窗,强制要求操作员输入当前登录密码或动态验证码。 - **必填操作事由**:操作前必须下拉选择或录入事由(如“消防巡检”、“医疗急救”、“钥匙失效人工放行”),且字数不得少于 10 字。 - **全要素审计日志**:自动抓取并记录:操作人账号、操作人真实姓名、终端客户端 IP、User-Agent、目标楼栋房间、门锁硬件 SN、操作原因、DMS 返回的 `operationId` 与执行结果。 --- ## 5. 门禁全生命周期审计轨迹设计 (`Audit Trail`) 系统必须在 `train_door_access_audit`(或 RuoYi 标准 `sys_oper_log` 基础上扩展)中建立不可篡改的门禁操作流水。 ### 5.1 审计要素清单 每条审计记录必须完整包含以下 14 个不可变字段: 1. `audit_id`: 全局唯一审计流水号 2. `business_type`: 业务类型(`GRANT` 授权下发, `REVOKE` 授权注销, `RETRY` 失败重试, `REMOTE_UNLOCK` 远程开锁) 3. `accommodation_id`: 关联的本地住宿事实 ID 4. `enrollment_id` & `student_name`: 目标学员信息 5. `dorm_building`, `dorm_floor`, `dorm_room`: 目标宿舍物理位置 6. `dms_lock_id` & `lock_hardware_id`: DMS 门锁标识 7. `credential_type`: 凭据类别(`ONLINE_PASSWORD`, `ONLINE_CARD`) 8. `dms_key_id`: DMS 返回的钥匙全局凭据 ID 9. `dms_operation_id`: DMS 异步执行任务流水号 10. `operation_result`: 最终结果(`SUCCESS`, `FAILED`, `TIMEOUT`) 11. `error_message`: 详细失败信息(若有) 12. `operator_id` & `operator_name`: 操作发起人(系统自动触发时标为 `SYSTEM_AUTO`) 13. `client_ip`: 发起操作的客户端 IP 14. `operate_time`: 操作发生时间戳 ### 5.2 响应数据持久化策略 (`Response Sanitization Policy`) - **禁止项**:绝不无脑把外部 DMS 返回的几千字节原始 JSON 直接整体塞入数据库的文本列中。 - **要求**:仅抽取核心对账字段进行结构化持久化;若出于排障目的保留原始请求与响应报文快照,**必须先经过脱敏过滤器(剔除明文密码与密钥)**后再写入 `sanitized_response_payload`。 --- ## 6. Wave 2 Implementation Result (Wave 2 implemented against Mock DMS only) - **阶段状态**:Wave 2 implemented against Mock DMS only。 - **安全红线核验结论**: - `PLAINTEXT_PASSWORD_PERSISTENCE_COUNT = 0`:反射测试断言 `TrainExternalOperation` 与 `TrainDormAuth` 绝无密码明文属性,实体中仅保留 `external_key_id`。 - `SECRET_LOGGING_COUNT = 0`:`DmsHttpClient` 与 `DmsOperationPoller` 全局应用 `sanitize` 过滤器,请求头与请求体中的 `password`、`token`、`appsecret` 均被强制替换为 `[PROTECTED]`。 - `LIVE_DMS_REQUEST_COUNT = 0`:开发与自动化测试期间严格仅使用内嵌 `MockDmsServer`,真实 DMS 地址仅保留于默认配置占位符,未发起任何公网请求。 - **迁移标记**: - `008_RUNTIME_FIRST_RUN = NOT_EXECUTED`,`008_RUNTIME_SECOND_RUN = NOT_EXECUTED`。 - `RUNTIME_MIGRATION_GATE_BEFORE_PRODUCTION = REQUIRED`。