请求头规范
本文档定义了 SlaunchX 后端识别的所有 HTTP 请求头,按来源层分类。作为前端开发者和内部团队的唯一事实来源。
架构概览
请求在到达后端应用之前,会经过四个层:
客户端(浏览器 / API 调用方)
→ Cloudflare(CDN + 边缘安全)
→ Nginx(网关反向代理)
→ Spring Boot(后端应用)每一层可能注入、透传或剥离请求头。下表按 来源 和 信任级别 对所有请求头进行分类。
L1: 客户端请求头(前端 / API 调用方设置)
这些请求头由调用方显式设置。后端会验证但不会盲目信任。
Web 链路(JWT 认证)
| 请求头 | 必填 | 描述 |
|---|---|---|
Authorization | 是 | 登录流程获取的 Bearer <JWT> 令牌 |
X-LOCALE | 否 | 应用语言偏好(如 en-US、zh-CN) |
X-Client-Hash | 条件 | 客户端指纹哈希。在端点启用指纹验证时必填(@GatewayValidation 配合 FingerprintHandler) |
X-Workspace-Id | 否 | 多工作空间用户的工作空间标识 |
X-Turnstile-Token | 条件 | Cloudflare Turnstile 挑战令牌。在 enableTurnstile=true 的端点必填。替代方式:cf-turnstile-response 查询参数 |
API 链路(HMAC 认证)
| 请求头 | 必填 | 描述 |
|---|---|---|
X-Api-Key | 是 | API Key 标识符(如 sk_live_abc123) |
X-Timestamp | 是 | Unix 时间戳(秒,UTC)。服务端拒绝偏差 > 60 秒的请求 |
X-Nonce | 是 | 唯一请求标识符(建议使用 UUID v4)。防止重放攻击 |
X-Signature | 是 | HMAC-SHA256 签名,Base64 编码。计算方式参见认证指南 |
X-LOCALE | 否 | 应用语言偏好 |
L2: 浏览器自动请求头(透明转发)
这些请求头由浏览器引擎设置,通过 Cloudflare 和 Nginx 原样转发。非浏览器客户端可以伪造。
| 请求头 | 描述 | 使用方 |
|---|---|---|
User-Agent | 浏览器/客户端标识字符串 | 会话指纹、风控引擎、审计日志 |
Accept-Language | 浏览器语言偏好 | 风控引擎上下文 |
Sec-CH-UA | Client Hints:浏览器品牌和版本 | 会话指纹 |
Sec-CH-UA-Platform | Client Hints:操作系统 | 会话指纹 |
Sec-CH-UA-Mobile | Client Hints:移动设备标识(?0 或 ?1) | 会话指纹 |
安全说明:这些请求头参与会话指纹计算(SessionFingerprintExtractor)。登录时的指纹与后续请求不匹配会触发 FINGERPRINT_MISMATCH(错误码 50030101)。
L3: Cloudflare 注入请求头(可信,客户端不可伪造)
这些请求头由 Cloudflare 边缘节点添加。后端将其视为权威来源。客户端无法设置或覆盖这些请求头 — Cloudflare 会剥离任何客户端提供的值。
自动注入(始终存在)
| 请求头 | 描述 |
|---|---|
CF-Connecting-IP | 客户端真实 IP 地址。ClientIpResolver 的首选来源 |
Cf-Ray | Cloudflare 请求追踪 ID。用于调试和风控审计追踪 |
Exposed-Credential-Check | 泄露凭据检测标记。启用 Cloudflare 泄露凭据检测功能后注入 |
Managed Transform(需在 Cloudflare 控制台配置)
需启用 "Add visitor location headers" Managed Transform。
| 请求头 | 描述 |
|---|---|
cf-ipcountry | ISO 3166-1 alpha-2 国家代码 |
cf-region | 区域或省份 |
cf-ipcity | 城市 |
cf-iplatitude | 纬度坐标 |
cf-iplongitude | 经度坐标 |
cf-postal-code | 邮编 |
cf-timezone | 客户端时区(如 America/Los_Angeles) |
配置路径:Cloudflare Dashboard > Rules > Transform Rules > Managed Transforms > "Add visitor location headers"。
L4: Nginx 注入请求头(可信,反向代理写入)
这些请求头由网关服务器上的 Nginx 反向代理写入。具有权威性,客户端无法影响。
| 请求头 | 描述 | 生成方式 |
|---|---|---|
X-Real-IP | 直连 IP(通常是 Cloudflare 边缘 IP) | $remote_addr |
X-Forwarded-For | 完整代理链 IP 列表 | $proxy_add_x_forwarded_for |
X-Forwarded-Proto | 原始请求使用的协议 | 硬编码 https |
X-Request-Id | 唯一请求追踪 ID | $msec-$connection-$connection_requests |
X-PORTAL-ACCESS-CODE | 从子域名解析的门户访问码 | Nginx map 块:子域名 → 访问码 |
门户访问码映射
X-PORTAL-ACCESS-CODE 不由前端设置。Nginx 根据子域名解析:
system-alpha.slaunchx.cc → map → $alpha_portal_access_code = "<portal-access-code>"
<tenant>-alpha.slaunchx.cc → map → $alpha_portal_access_code = "<portal-access-code>"注意:以上示例值为占位符。实际访问码存储在
/etc/nginx/snippets/slaunchx-*-portals.conf中,不得提交到文档。
后端的 PortalAccessCodeHandler 会根据数据库验证此访问码,确定 portalType 和 institutionBizId。
IP 解析优先级
ClientIpResolver 使用以下优先级链确定客户端真实 IP:
1. CF-Connecting-IP (L3 — Cloudflare,权威来源)
2. X-Real-IP (L4 — Nginx,回退)
3. X-Forwarded-For[0] (L4 — 第一条,无 CF 时可能被伪造)
4. request.getRemoteAddr()(直连 IP,最后手段)在标准 Cloudflare + Nginx 架构下,CF-Connecting-IP 始终存在且被使用。
代码参考
| 类 | 模块 | 职责 |
|---|---|---|
ClientHeaderExtractor | slaunchx-infra-gateway-core | 将 L1/L2/L3 请求头提取到 ClientInfo 记录 |
ClientIpResolver | slaunchx-infra-gateway-core | IP 解析优先级链 |
SessionFingerprintExtractor | slaunchx-infra-gateway-core | 从请求头构建会话指纹 |
GatewayRiskContextBuilder | slaunchx-infra-risk | 从所有请求头层构建风控上下文 |
ValidationContext | slaunchx-infra-gateway-core | 读取 X-Request-Id 和 X-Forwarded-For |
安全边界
| 原则 | 实现方式 |
|---|---|
| L3/L4 请求头可信 | Cloudflare 和 Nginx 是唯一来源。后端不验证其格式。 |
| L1 请求头需验证 | JWT 会被验证,HMAC 会被重新计算,Turnstile 令牌会通过 CF API 检查 |
| L2 请求头仅供参考 | 用于指纹和风险评分,从不用于访问控制决策 |
| 默认拒绝 | 端点无 @ApiScope = 403。WEB 链路缺少 X-PORTAL-ACCESS-CODE = 门户解析失败 |
| 不向客户端转发请求头 | L3/L4 请求头名称和值永远不会出现在 API 响应中 |