spec.md 2.3 KB

replay-guard Specification

Purpose

TBD - created by archiving change add-request-auth-replay-guard. Update Purpose after archive.

Requirements

Requirement: 时间窗校验

mjava 基座 SHALL 拒绝时间戳超出配置窗口的请求,以限制重放攻击的有效窗口。

Scenario: 时间戳在窗口内

  • WHEN X-MJ-Timestamp 与服务端当前时间差 ≤ mjava.auth.window(默认 300 秒)
  • THEN 进入后续 Nonce 与签名校验

Scenario: 时间戳超窗

  • WHEN 时间差 > window(无论提前还是滞后)
  • THEN 返回 401 { code: "AUTH_TIMESTAMP_OUT_OF_WINDOW" }
  • AND 审计日志记录 clientTimestampserverTimestamp 供排查

Requirement: Nonce 去重

mjava 基座 SHALL 通过 Nonce 缓存实现在时间窗内的一次性请求保证。同一 Nonce 在窗口期内只允许通过一次。

Scenario: 首次 Nonce 被接受

  • WHEN 请求携带之前未见过的 X-MJ-Nonce
  • THEN NonceCache.putIfAbsent(nonce) 成功
  • AND 请求进入签名校验

Scenario: Nonce 被重放

  • WHEN 请求携带之前已见过的 Nonce(仍在 TTL 内)
  • THEN NonceCache.putIfAbsent 返回 false
  • AND 返回 401 { code: "AUTH_NONCE_REPLAYED" }

Scenario: Nonce 缓存容量上限

  • WHEN NonceCache 达到 mjava.auth.nonce-cache-size 上限
  • THEN 按 LRU 策略淘汰最旧条目
  • AND 淘汰不影响未淘汰 Nonce 的判定正确性

Requirement: Nonce 缓存 TTL 设置

NonceCache 的 TTL MUST 略长于 mjava.auth.window,以避免边界时间戳被错误接受。

Scenario: TTL 等于窗口 + 30s

  • WHEN NonceCache 初始化
  • THEN TTL = mjava.auth.window + 30
  • AND 例:window=300 → TTL=330

Requirement: 单实例内存限制声明

Phase 1 的 Nonce 去重 SHALL 在单 JVM 实例内生效;多实例部署时同一 Nonce 可能被两个实例各接受一次。这是已知限制,不在本 change 范围。

Scenario: 多实例部署告警

  • WHEN 生产部署判定需要多实例横向扩展
  • THEN 运维必须评估是否升级为分布式 Nonce(Redis),独立走新 change 提案
  • AND 本 change 的 NonceCache 配置 nonce-cache-size 建议单实例足够承载高峰 QPS × window 秒的组合