安全机制
纵深防御
┌─────────────────────────────────────────────────────────────┐
│ 第 1 层:TypeScript │
│ 编译时类型检查 │
├──────────────────────────────────────────────────────────── ─┤
│ 第 2 层:输入验证 │
│ API 级别的清理和格式检查 │
├─────────────────────────────────────────────────────────────┤
│ 第 3 层:参数化 SQL │
│ SQL 注入防护 │
├─────────────────────────────────────────────────────────────┤
│ 第 4 层:数据库约束 │
│ CHECK、UNIQUE、FK 约束保证数据完整性 │
├─────────────────────────────────────────────────────────────┤
│ 第 5 层:中间件 │
│ 路由级别的认证和 RBAC │
├─────────────────────────────────────────────────────────────┤
│ 第 6 层:限流 │
│ 基于 Redis 的滥用防护 │
└─────────────────────────────────────────────────────────────┘
认证安全
密码哈希(bcrypt)
// 注 册:10 轮 = ~100ms 故意慢速
const hash = await bcrypt.hash(password, 10);
// 登录:使用存储的盐重新哈希输入并比较
const valid = await bcrypt.compare(inputPassword, storedHash);
| 特性 | 安全优势 |
|---|---|
| 单向 | 无法从哈希反推密码 |
| 加盐 | 相同密码 → 每次不同的哈希 |
| 慢速(~100ms) | 抵御暴力破解 |
| 成本因子 | 可随硬件升级增加轮数 |
JWT 安全
| 方面 | 实现 |
|---|---|
| 存储 | httpOnly cookie(JS 无法访问) |
| 签名 | 使用 AUTH_SECRET 的 HMAC-SHA256 |
| 载荷 | 仅包含 id、email、role |
| 永不存储 | 密码、信用卡、密钥 |
输入验证
数量验证
// 类型检查(无强制转换)
if (typeof quantity !== "number" || !Number.isInteger(quantity)) {
return NextResponse.json({ error: "数量格式无效" }, { status: 400 });
}
// 范围检查
if (quantity < 1 || quantity > 100) {
return NextResponse.json({ error: "数量必须在 1-100 之间" }, { status: 400 });
}