2.3.1.知识包推送与集群同步安全配置

适用对象:架构师、系统维护人员 适用范围:知识包匿名推送端点(KnowledgePackageReceiverServlet)与集群节点同步端点(DynamicServletHandler) 说明:本节仅描述配置项,不含实现细节。客户端与服务端必须同时升级,无向后兼容。 关联章节:2.3.系统默认参数覆盖、3.8.集群管理、11.5.1.服务端集群搭建


1. 概述

对知识包推送与集群同步端点做端到端的 HMAC-SHA256 请求签名加固,替换原有的明文 _u/_p 弱凭证校验。核心变化:

  • 请求通过 HTTP 头传递签名信息(X-Urule-*),不进入 URL,避免落入访问日志。
  • 接收端启用防重放(时间戳窗口 + nonce 去重)、body 大小限流、Zip Slip 防护、异常不回显。
  • urule.pushSignSecret 为必填项,缺失时接收端启动失败。

2. 配置项一览

配置项 必填 默认值 说明
urule.pushSignSecret 是 无(内置默认常量仅用于告警检测) 签名密钥,HMAC-SHA256 计算所用 secret
urule.pushBodyMaxSize 否 104857600(约 100 MB) 接收端单次请求 body 大小上限,超出直接拒绝
urule.pushSignTimeWindow 否 300000(毫秒,即 5 分钟) 时间戳窗口;nonce 去重 TTL 与窗口一致

3. 配置读取优先级

每个属性按以下顺序解析,高优先级覆盖低优先级:

1. JVM 系统属性(-D,最高优先)
2. urule.properties 文件(PropertyConfigurer)
3. 内置默认值

示例:

# 方式一:启动参数(系统级,最高优先)
-Durule.pushSignSecret=your-strong-secret
-Durule.pushBodyMaxSize=209715200
-Durule.pushSignTimeWindow=600000

# 方式二:urule.properties 文件
urule.pushSignSecret=your-strong-secret
urule.pushBodyMaxSize=209715200
urule.pushSignTimeWindow=600000

提示:两种配置方式均可,系统属性 -D 可临时覆盖文件配置,便于运维在不变更发布包的情况下调整阈值。


4. 各配置项说明

4.1 urule.pushSignSecret(必填)

  • 客户端(console 推送端)与接收端(core 接收端)必须配置为相同值。
  • 为空:视为必填缺失,接收端 Servlet.init 启动时 SEVERE 告警并启动失败(快速失败)。
  • 等于内置默认常量:启动时 SEVERE 告警(提示未修改默认口令)。
  • 建议:使用足够长度的随机密钥,通过 -D 注入或妥善保管 urule.properties 文件权限。

4.2 urule.pushBodyMaxSize(可选)

  • 接收端一次性读取并校验 body 的上限,单位为字节。
  • 超过该值的请求直接拒绝,避免无限读取。
  • 默认约 100 MB;如需推送更大知识包,按实际需求上调。

4.3 urule.pushSignTimeWindow(可选)

  • 时间戳窗口(毫秒),用于防重放校验。
  • 接收端拒绝窗口外(默认 ±5 分钟)的请求。
  • nonce 去重集合的 TTL 与此窗口一致;多实例部署时,时间戳窗口为首要防重放防线。

5. 签名机制(运维关注点)

  • 签名头(请求头,不进入 URL):

    | Header | 含义 | | --- | --- | | X-Urule-Timestamp | 请求时间戳(毫秒) | | X-Urule-Nonce | 一次性随机串,用于去重 | | X-Urule-Body-Digest | SHA-256(body) 的 hex 摘要 | | X-Urule-Sign | HMAC-SHA256(secret, timestamp|nonce|bodyDigestHex) 的 hex |

  • 校验内容(接收端 PushSignature.verify):签名正确性 + 时间戳窗口 + nonce 去重 + body 大小。

  • 校验失败 / 异常仅返回通用文案(如「签名校验失败」「请求体过大」「服务器内部错误」),完整堆栈仅记录服务端日志,不回显给客户端。

6. 部署检查清单

  • [ ] 客户端与接收端同时部署新版本(不兼容旧版 _u/_p 校验)。
  • [ ] 所有节点的 urule.pushSignSecret 配置一致且非默认/非空。
  • [ ] 多实例部署时各节点时钟同步(保障时间戳窗口校验有效)。
  • [ ] 如知识包体积较大,确认 urule.pushBodyMaxSize 已按需调整。
  • [ ] 接收端启动日志无 SEVERE 级别「默认口令 / 缺失 secret」告警。
  • [ ] 集群同步链路(DynamicServletHandler)与推送链路均已完成签名改造。

7. 备注

  • 受影响模块:urule-core-pro(接收端校验 + 共享签名工具 + Zip Slip 修复)、urule-console-pro(推送端签名 + 集群端点校验)。urule-pro-boot2/boot3 复用 core-pro 的 Servlet,无需额外注册。
  • 兼容 JDK 1.8 运行环境,加解密仅使用 JDK 自带 javax.crypto.Mac 与 java.security.MessageDigest,无新增第三方依赖;该方案同样可在 JDK 21/23 下运行(详见第 8 节)。
  • requestRemoteJars / remoteCheck(client→repo 拉取链路)不在本次加固范围,仍保留原有 _u/_p 机制。

8. JDK 21/23 兼容性说明

本节供运维/架构在决定升级运行 JDK 版本时参考。结论:当前 HMAC-SHA256 + SHA-256 方案在 JDK 21/23 下完全兼容,无需为算法本身做任何改动。

8.1 算法层兼容(无需改动)

当前仅使用 JDK 8 时代即存在、且在新版 JDK 中仍长期保留于 java.base 的核心 API:

用途 使用的 API 在 JDK 21/23 的状态
HMAC 计算 javax.crypto.Mac java.base,始终可用
body 摘要 java.security.MessageDigest java.base,始终可用
发送请求 HttpURLConnection / setRequestProperty java.net(java.base),未废弃
Zip Slip 校验 File.getCanonicalPath() java.base,仍可用
属性读取 System.getProperty 核心 API,无变化

签名计算显式使用 UTF_8 字符集(如 secret.getBytes(UTF_8)),规避了 JDK 18+ 默认字符集改为 UTF-8(JEP 400)带来的跨版本行为差异,跨 JDK 行为一致。

8.2 模块系统(JPMS)不会拦截

即便应用以 JPMS 模块化方式运行(module-info.java),javax.crypto、java.security、java.net 均位于 java.base,对任意模块默认可见,无需额外 requires。不会出现"升级 JDK 后编译报模块不可访问"的问题。

8.3 需注意的环境级差异(非算法问题)

  1. Security Manager 移除(JDK 17+,JEP 411):当前签名/摘要逻辑不依赖 SM,无影响。
  2. TLS 默认值变化(JDK 11+,仅 HTTPS 推送链路):若推送走 HTTPS,新版 JDK 默认启用 TLS 1.3、禁用 TLS 1.0/1.1,且 JDK 16+ 默认禁用 SHA-1 签名证书链。若接收端仍用老 TLS 或 SHA-1 证书,会连接失败——与 HMAC 逻辑无关,需运维核对对端配置。
  3. 编译目标约束:项目仍以 JDK 1.8 为目标(字节码 major 52),可在任何更高版本 JVM 上运行;只需继续遵守"不引入 JDK 9+ API"的约束(如不使用 Path.toRealPath)。

8.4 验证清单

  • [ ] 算法层无需改动:HMAC-SHA256 / SHA-256 在 21/23 均内置默认可用(无限强度策略自 JDK 8u161 起默认开启)。
  • [ ] 确认未使用 javax.xml.bind、CORBA、sun.misc.* 等 JDK 11+ 已移除的包(本方案未涉及)。
  • [ ] 若启用 HTTPS 推送,核对接收端 TLS 版本与证书(避免 SHA-1/老 TLS 被新版 JDK 拒绝)。
  • [ ] 若以 JPMS 模块运行,无需为 crypto/network 额外 requires(已在 java.base)。
  • [ ] 保持 getBytes(UTF_8) 等显式字符集写法,避免默认字符集差异。

results matching ""

    No results matching ""