Day 094 — 安全编程 · 图解
1. 注入攻击原理
SQL 注入攻击流程:
用户输入: ' OR '1'='1' --
┌──────────────────────────────────────┐
│ 未过滤的输入 │
│ "SELECT * FROM users WHERE │
│ name='" + input + "' AND pass='xxx'" │
└──────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 恶意 SQL │
│ SELECT * FROM users WHERE │
│ name='' OR '1'='1' --' AND pass='xxx'│
└──────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ 攻击结果 │
│ 返回所有用户,绕过认证 │
└──────────────────────────────────────┘
防护: 参数化查询
┌──────────────────────────────────────┐
│ SQL: SELECT * FROM users │
│ WHERE name=? AND pass=? │
│ 参数: (input, password) │
└──────────────────────────────────────┘
输入被当作数据,不是代码!
2. 密码存储安全
❌ 不安全的密码存储:
明文存储:
数据库: password = "my_secret_123"
数据库泄露 → 所有密码泄露
简单哈希 (无盐):
数据库: password = sha256("my_secret_123")
彩虹表攻击 → 秒级反推
✅ 安全的密码存储:
bcrypt:
盐: 随机生成 (16 bytes)
哈希: bcrypt(password + salt, rounds=12)
数据库: $2b$12$随机盐+哈希值
优势:
- 每个密码独立盐 → 彩虹表无效
- rounds=12 → 每次验证 ~250ms → 暴力破解极慢
- 专业算法 → 经过安全审计
3. JWT 认证流程
登录流程:
┌────────┐ ┌────────┐
│ 客户端 │ │ 服务器 │
└────┬───┘ └────┬───┘
│ │
│ 1. POST /login │
│ {username, password} │
│────────────────────────────►│
│ │ 2. 验证密码
│ │ 3. 生成 JWT
│ 4. 返回 JWT Token │
│◄────────────────────────────│
│ │
│ 5. GET /api/data │
│ Authorization: Bearer JWT │
│────────────────────────────►│
│ │ 6. 验证 JWT
│ │ 7. 检查权限
│ 8. 返回数据 │
│◄────────────────────────────│
JWT Token 结构:
┌──────────────────────────────────────────────────────┐
│ Header.Payload.Signature │
├──────────────────────────────────────────────────────┤
│ Header: {"alg":"HS256","typ":"JWT"} │
│ Payload: {"sub":"123","exp":1700000000} │
│ Signature: HMAC-SHA256(header.payload, secret) │
└──────────────────────────────────────────────────────┘
4. 对称 vs 非对称加密
对称加密 (AES):
同一个密钥用于加密和解密
明文 ──[密钥K]──► 密文 ──[密钥K]──► 明文
优点: 速度快,适合大数据
缺点: 密钥分发困难
非对称加密 (RSA):
公钥加密,私钥解密
公钥 (公开) 私钥 (保密)
│ │
▼ ▼
明文 ──[公钥]──► 密文 ──[私钥]──► 明文
优点: 安全分发密钥
缺点: 速度慢,只适合小数据
实际应用: 混合加密
1. 用 RSA 交换 AES 密钥
2. 用 AES 加密实际数据
3. 兼顾安全性和性能
5. 速率限制原理
暴力破解防护:
请求次数: 1 2 3 4 5 6 7 8 9 10
│ │ │ │ │ │ │ │ │ │
状态: ✅ ✅ ✅ ✅ ✅ 🚫 🚫 🚫 🚫 🚫
│ │
│ └── 超过限制,拒绝访问
└── 5分钟窗口内的尝试次数
实现方式:
┌─────────────────────────────────────────┐
│ IP/用户名 → [尝试记录列表] │
│ │
│ 每次登录: │
│ 1. 清理过期记录 (>5分钟) │
│ 2. 检查尝试次数 (<5次?) │
│ 3. 允许/拒绝 │
│ 4. 记录本次尝试 │
└─────────────────────────────────────────┘
6. 安全编码检查清单
输入验证:
✅ 所有输入都验证
✅ 白名单 > 黑名单
✅ 长度限制
✅ 类型检查
输出编码:
✅ HTML 转义 (防 XSS)
✅ URL 编码
✅ SQL 参数化
认证授权:
✅ 密码哈希 (bcrypt)
✅ 速率限制
✅ Session/Token 管理
✅ 最小权限原则
加密:
✅ TLS/HTTPS
✅ AES-256-GCM
✅ RSA-2048+
✅ 密钥管理
日志审计:
✅ 记录安全事件
✅ 不记录敏感数据
✅ 监控异常行为