wz-golang-server/docs/security_and_payload_crypto.md

128 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 接口安全校验与请求/响应加密说明
本文档说明系统已有的两套机制:
1. 安全校验(请求头签名)
2. 请求/响应参数加解密AES-GCM
并给出前端对接方式与示例。
## 一、机制概览
### 1. 安全校验(签名)
- 入口中间件:`server/middleware/security.go`
- 目的:防止非法请求与重放
- 校验内容:请求头签名 + 时间戳
- 有效期5 分钟内
- 白名单:`/swagger/`、`/swagger/index.html`
### 2. 请求/响应加解密Payload Crypto
- 入口中间件:`server/middleware/payload_crypto.go`
- 加密算法AES-GCM密钥来自 `payload_crypto.secret_key`
- 加密载荷结构:
- `nonce`Base64
- `ciphertext`Base64
- 可独立控制:
- 仅加密响应
- 仅解密请求
- 请求强制加密
## 二、当前开发环境默认行为config.dev.yaml
- `security.enable = false`
- 不要求签名头
- `payload_crypto.enable = true`
- 框架开启,但请求/响应方向开关关闭
- `payload_crypto.request.enable = false`
- `payload_crypto.response.enable = false`
结论:开发环境默认不需要前端计算签名,也不会返回加密响应。
## 三、前端对接方式
### 1. 安全校验(签名)对接
`security.enable = true` 时必须携带:
- `X-App-Timestamp`:毫秒时间戳
- `X-App-Sign``MD5(timestamp + secretKey)`
- `secretKey` 来自 `security.secret_key`
请求示例(伪代码):
```text
timestamp = 当前毫秒时间戳
sign = md5(timestamp + secretKey)
Headers:
X-App-Timestamp: <timestamp>
X-App-Sign: <sign>
```
注意:
- 服务器允许时间偏差 5 分钟。
- 若请求不在白名单且缺少签名或时间戳,将返回 403。
### 2. 请求加密(可选)
`payload_crypto.enable = true``payload_crypto.request.enable = true` 时:
-`payload_crypto.request.required = true`,所有请求必须加密。
-`required = false`,是否加密由请求头决定。
请求头:
- `X-App-Encrypt: 1`(头名来自 `payload_crypto.header_key`
请求体格式JSON
```json
{
"nonce": "Base64Nonce",
"ciphertext": "Base64Ciphertext"
}
```
加解密规则:
- AES-GCM
- nonce 长度使用 GCM 标准长度12 bytes编码后为 Base64 字符串)
- 明文为原始 JSON 请求体
### 3. 响应加密(可选)
`payload_crypto.enable = true``payload_crypto.response.enable = true` 时:
- 服务端返回加密响应
- 响应头会带:`X-App-Encrypt: 1`
- 响应体同样为:
```json
{
"nonce": "Base64Nonce",
"ciphertext": "Base64Ciphertext"
}
```
前端处理流程:
1. 判断响应头 `X-App-Encrypt` 是否为真(非空、非 0、非 false
2. 若为真,用 `payload_crypto.secret_key` 进行 AES-GCM 解密。
3. 解密得到的明文即为原始 JSON 响应。
## 四、密钥派生规则(前端需要一致)
加密密钥派生规则在 `server/common/payload_crypto.go`
1.`secret_key` 是 Base64且解码后长度为 16/24/32 字节,直接使用。
2. 否则若 `secret_key` 的原始长度为 16/24/32 字节,直接使用原始字节。
3. 否则对 `secret_key` 做 SHA-256取 32 字节作为 AES key。
前端必须严格按上述规则派生密钥,否则无法解密。
## 五、建议的对接策略
- 开发联调:先关闭签名与加密,仅验证业务流程。
- 灰度/生产:
- 开启 `security.enable`,强制签名校验。
- 按需开启 `payload_crypto.response.enable`,保护敏感响应。
- 若需要强制请求加密,再开启 `payload_crypto.request.required`
## 六、相关配置位置
- 安全校验配置:`server/config/config.*.yaml` -> `security`
- 加解密配置:`server/config/config.*.yaml` -> `payload_crypto`
- 中间件实现:
- `server/middleware/security.go`
- `server/middleware/payload_crypto.go`
- 加解密工具:`server/common/payload_crypto.go`