# 安全规范示例

> 本文件为 Web 应用安全规范示例，覆盖 OWASP Top 10 常见风险及防御措施。
> 复制到项目后按需修改，或作为 `.speccore/RULES/security.md` 的素材。

---

## 1. 认证与授权

### 1.1 密码安全

| 规则 | 要求 |
|:---|:---|
| 最小长度 | 8 位 |
| 复杂度 | 大小写字母 + 数字 + 特殊字符，至少两种 |
| 哈希算法 | bcrypt / scrypt / Argon2，禁止 MD5 / SHA1 |
| 盐值 | 每个密码独立随机盐 |
| 历史密码 | 禁止复用最近 5 次密码 |
| 错误提示 | 登录失败时统一提示"用户名或密码错误"，不暴露账号是否存在 |

### 1.2 会话管理

| 规则 | 要求 |
|:---|:---|
| Token 有效期 | Access Token 2 小时，Refresh Token 7 天 |
| Token 存储 | 禁止 localStorage 存敏感 Token，使用 httpOnly Cookie |
| 并发登录 | 同一账号最多 3 处同时登录，超限踢掉最早会话 |
| 异常检测 | 异地登录、短时间内大量失败尝试 → 触发二次验证或锁定账号 |
| 登出处理 | Token 加入黑名单，立即失效 |

### 1.3 权限控制

- **最小权限原则：** 每个角色只给完成工作所需的最小权限
- **数据权限隔离：** 用户只能访问自己的数据，管理员只能访问本组织数据
- **敏感操作二次确认：** 删除账号、修改密码、转账等操作需再次验证身份
- **API 鉴权全覆盖：** 每个接口必须有鉴权注解/装饰器，禁止默认公开

---

## 2. 输入校验

### 2.1 通用规则

- **服务端必须校验：** 前端校验只是体验优化，服务端校验才是安全防线
- **白名单优先：** 明确允许什么，而不是禁止什么
- **参数化查询：** 所有数据库操作必须使用预编译语句，禁止字符串拼接 SQL

### 2.2 各类型输入校验

| 类型 | 校验规则 | 示例 |
|:---|:---|:---|
| 手机号 | `^1[3-9]\d{9}$` | 13800138000 |
| 邮箱 | RFC 5322 简化版，长度 ≤ 128 | user@example.com |
| 用户名 | 2-20 位，中文/字母/数字/下划线，不以数字开头 | user_123 |
| 密码 | 8-32 位，至少两种字符类型 | MyP@ssw0rd |
| URL | 协议限定 http/https，禁止 file/javascript | https://example.com |
| 整数 | 明确范围，防止溢出 | 1 ~ 999999 |
| 文件路径 | 禁止 `../` `..\` 路径遍历 | — |
| HTML 内容 | 富文本必须白名单过滤标签 | 只允许 `<p>` `<b>` `<i>` 等安全标签 |

### 2.3 文件上传安全

- **白名单校验后缀：** 只允许 `.jpg` `.png` `.pdf` 等预期格式
- **MIME 类型校验：** 不能仅靠后缀，需读取文件头验证真实类型
- **大小限制：** 单文件最大 50MB，超出拒绝
- **病毒扫描：** 文件上传后先扫描再落盘
- **存储隔离：** 上传文件存储在非 Web 目录，通过接口代理访问
- **重命名存储：** 使用随机文件名 + 原始文件名映射，防止覆盖攻击

---

## 3. 输出编码

### 3.1 XSS 防御

| 场景 | 防御方式 |
|:---|:---|
| 反射型 XSS | 所有 URL 参数输出到页面时 HTML 编码 |
| 存储型 XSS | 入库前过滤/编码，出库时再次编码 |
| DOM 型 XSS | 禁止 `innerHTML` / `document.write`，使用 `textContent` |
| 富文本 | 使用 DOMPurify 等库白名单过滤标签 |

**编码规则：**
```
<  →  &lt;
>  →  &gt;
"  →  &quot;
'  →  &#x27;
&  →  &amp;
```

### 3.2 JSONP / CORS

- **禁止 JSONP：** 使用 CORS 代替，防止回调劫持
- **CORS 白名单：** `Access-Control-Allow-Origin` 必须指定具体域名，禁止 `*`
- **Credentials 限制：** 携带 Cookie 的请求必须同时校验 Origin

---

## 4. 敏感数据处理

### 4.1 传输加密

- **全站 HTTPS：** 禁止 HTTP 访问，HSTS 头 `max-age` ≥ 31536000
- **敏感接口额外加密：** 支付、身份证等字段使用 AES-256-GCM 加密传输
- **证书管理：** 使用 Let's Encrypt 自动续期，到期前 30 天告警

### 4.2 存储加密

| 数据类型 | 加密方式 | 说明 |
|:---|:---|:---|
| 密码 | bcrypt (cost=12) | 不可逆哈希 |
| 身份证号 | AES-256-GCM | 对称加密，密钥存 KMS |
| 银行卡号 | AES-256-GCM + 脱敏展示 | 展示时只显示后 4 位 |
| 手机号 | 脱敏存储 | 138****8000 |
| Token | HMAC-SHA256 签名 | 防止篡改 |

### 4.3 日志脱敏

**禁止打印：**
- 密码、Token、Session ID
- 身份证号、银行卡号
- 手机号（可脱敏后打印）
- 加密密钥

**日志示例：**
```
# ❌ 错误
[ERROR] 用户登录失败，密码=123456，手机号=13800138000

# ✅ 正确
[INFO] 用户登录失败，userId=10086，reason=密码错误
```

---

## 5. 常见攻击防御

### 5.1 SQL 注入

**防御：**
- 全部使用预编译语句 / ORM 参数化查询
- 禁止字符串拼接 SQL
- 数据库账号最小权限（禁止 DROP/GRANT）

**危险代码：**
```java
// ❌ 错误
String sql = "SELECT * FROM users WHERE name = '" + name + "'";

// ✅ 正确
String sql = "SELECT * FROM users WHERE name = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, name);
```

### 5.2 CSRF

**防御：**
- 使用 `SameSite=Strict` Cookie
- 敏感操作加 CSRF Token 校验
- 校验 `Origin` / `Referer` 头

### 5.3 SSRF

**防御：**
- 禁止服务端请求用户传入的 URL
- 如需请求，校验目标 IP 不在内网段（10.x.x.x, 172.16-31.x.x, 192.168.x.x）
- 使用白名单限制可访问的外部域名

### 5.4 越权访问

**防御：**
- 每个数据操作前校验当前用户是否有权访问该数据
- 禁止通过修改 URL 参数访问他人数据（如 `/orders/{id}` 必须校验订单归属）
- 管理员接口单独路由前缀 `/admin/`，加额外鉴权层

### 5.5 重放攻击

**防御：**
- 接口加时间戳校验（请求时间 ±5 分钟内有效）
- 敏感接口加 Nonce（一次性随机数）
- 支付类接口必须幂等

---

## 6. 安全 Headers

```
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
```

---

## 7. 安全开发清单

### 7.1 代码提交前

- [ ] 密码/密钥未硬编码在代码中
- [ ] 无 `console.log` 打印敏感信息
- [ ] SQL 全部使用参数化查询
- [ ] 用户输入全部校验后再使用
- [ ] 文件上传有类型/大小限制

### 7.2 上线前

- [ ] HTTPS 已配置，HTTP 自动跳转
- [ ] 安全 Headers 已全部添加
- [ ] 敏感接口有速率限制
- [ ] 日志已脱敏处理
- [ ] 数据库账号权限最小化
- [ ] 第三方依赖无已知高危漏洞（`npm audit` / `snyk` 扫描）
- [ ] 渗透测试通过（或至少自查 OWASP Top 10）

### 7.3 运行期

- [ ] 异常登录告警（异地、短时间大量失败）
- [ ] 敏感操作审计日志（谁在什么时间做了什么）
- [ ] 定期轮换密钥（Token 签名密钥、数据库加密密钥）
- [ ] 安全漏洞响应流程（发现漏洞后 24 小时内修复）
