# request-auth Specification ## Purpose TBD - created by archiving change add-request-auth-replay-guard. Update Purpose after archive. ## Requirements ### Requirement: HMAC 签名校验 mjava 基座 SHALL 提供可配置的 HMAC-SHA256 请求签名校验机制。当 `mjava.auth.enabled=true` 时,所有非豁免请求 MUST 通过签名校验才能进入业务 Controller。 #### Scenario: 合法签名请求通过 - **WHEN** 请求携带完整四个 Header(`X-MJ-Key` / `X-MJ-Timestamp` / `X-MJ-Nonce` / `X-MJ-Signature`) - **AND** 签名 = `HMAC-SHA256(secret, timestamp + "\n" + nonce + "\n" + method + "\n" + path + "\n" + bodyHash)` - **THEN** 请求被放行到 Controller - **AND** MDC 写入 `authKey` 字段供日志追溯 #### Scenario: 签名不匹配 - **WHEN** 计算出的签名与 Header 中 `X-MJ-Signature` 不一致 - **THEN** 返回 `403 { code: "AUTH_SIGNATURE_INVALID" }` - **AND** 响应 message 不包含期望签名值(避免泄露线索) - **AND** 审计日志记录 `authKey + path + latencyMs` #### Scenario: Header 缺失 - **WHEN** 四个必备 Header 中任一缺失 - **THEN** 返回 `401 { code: "AUTH_HEADER_MISSING" }` - **AND** 响应不说明具体缺失哪个 ### Requirement: 豁免机制 本能力 SHALL 支持三级豁免策略,优先级从上到下:全局开关 > 路径豁免 > 注解豁免。 #### Scenario: 全局关闭 - **WHEN** `mjava.auth.enabled=false` - **THEN** 所有请求跳过鉴权,行为等同于 enable 前的裸奔状态 #### Scenario: 路径豁免 - **WHEN** 请求路径匹配 `mjava.auth.exempt-paths` 列表中任一 Ant 风格模式 - **THEN** 跳过签名校验 - **AND** 典型清单:`/actuator/**`(健康检查)、`/api/*/callback/**`(第三方 webhook) #### Scenario: 注解豁免 - **WHEN** 目标 Controller 方法或其类带 `@NoAuth` 注解 - **THEN** 签名校验跳过 - **AND** 注解识别发生在 `HandlerInterceptor.preHandle`(能访问到 `HandlerMethod`) ### Requirement: 密钥配置 `secret` MUST 通过环境变量注入,禁止硬编码。`enabled=true` 但 `secret` 为空时 MUST 拒绝启动或拒绝请求。 #### Scenario: secret 未配置 - **WHEN** `mjava.auth.enabled=true` 但 `mjava.auth.secret` 为空或未设置 - **THEN** 启动时打 ERROR 日志 - **AND** 所有受保护请求返回 `503 { code: "AUTH_CONFIG_MISSING" }` #### Scenario: secret 从环境变量读取 - **WHEN** `application.yml` 中 `secret: ${AUTH_SECRET}` - **AND** 部署环境设置 `AUTH_SECRET` 变量 - **THEN** 启动时成功加载,后续请求按此密钥校验