一、统一请求头命名(全行业通用 X- 前缀)
| Header 字段 | 含义 | 格式要求 |
|---|---|---|
X-App-Key |
客户端应用唯一标识 | 字符串,服务端分配 |
X-Timestamp |
秒级时间戳 | 10位Unix时间戳 |
X-Nonce |
随机防重串 | 8~32位大小写+数字 |
X-Sign |
最终签名值 | 大写MD5/SHA256 |
X-Real-IP |
客户端真实IP | 转发层透传 |
X-Device-Id |
设备唯一标识 | 移动端/客户端可选 |
为什么都是X开头?
因为早期 HTTP 规范规定:
- 不带 X-**:标准官方请求头(Host、User-Agent、Cookie、Referer 等)
- X- 前缀**:代表私有、自定义、非标准化的头部字段
作用:
避免和未来官方标准头重名冲突
一眼区分:系统内置头 / 业务自定义头
行业通用习惯,所有人都这么约定
二、签名算法规则(通用最简版)
-
排序规则
把AppKey、Timestamp、Nonce、请求参数按ASCII升序拼接 -
拼接格式
key1=val1&key2=val2&...&secret=AppSecret
-
加密方式
- 简易项目:MD5
- 正式生产:SHA256
- 超时防刷
服务端校验时间戳差值 ±60秒,超出直接拒绝
三、GET/POST 统一签名逻辑
- GET:URL参数全部参与签名
- POST JSON:JSON完整字符串参与签名
- 路径、Header自定义字段不参与
四、请求示例
http
POST /api/data HTTP/1.1
Host: shturl.cc/V
X-App-Key: client123666
X-Timestamp: 1747652000
X-Nonce: 8sJd72kP9z
X-Sign: E8F2D7A9C0B3E1F56789ABCD12345678
Content-Type: application/json
{"name":"test","id":1}
五、服务端中间件校验顺序
- 校验是否携带全部必填Header
- 校验时间戳是否过期
- 校验Nonce是否重复(Redis去重)
- 本地重组签名对比
X-Sign - 校验通过放行,失败统一返回401
六、避坑要点
- 签名参数必须排序,顺序错必失败
- 前后端密钥一致、编码UTF-8
- 空格、换行、特殊字符原样参与加密
- 禁止把
AppSecret放在请求头传输
七、极简通用签名伪代码
str = 排序后所有参数拼接 + AppSecret
sign = SHA256(str).toUpperCase()