Kamixitong/docs/CSRF_CONFIG_GUIDE.md
2025-12-12 11:35:14 +08:00

263 lines
5.9 KiB
Markdown
Raw Permalink 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.

# 🔐 CSRF保护配置指南
## 📋 问题描述
KaMiXiTong系统在移除`csrf.exempt(api_bp)`后所有API请求都受到CSRF保护导致前端API调用返回400错误。
**错误表现**
```
Failed to load resource: the server responded with a status of 400 (BAD REQUEST)
API request failed: Error: 400: BAD REQUEST
```
## ✅ 解决方案
### 当前配置
我们已恢复对API蓝图的CSRF豁免
```python
# app/__init__.py
from app.api import api_bp
app.register_blueprint(api_bp, url_prefix=f'/api/{app.config["API_VERSION"]}')
csrf.exempt(api_bp) # 对API豁免CSRF
```
### 配置原理
#### 1. API豁免CSRF的原因
-**API有独立的认证机制** - 需要登录token或session
-**非浏览器端调用** - API主要供前端AJAX调用
-**CORS已配置** - 跨域访问已控制
-**其他安全措施** - 频率限制、参数验证等
#### 2. Web表单保持CSRF保护
-**浏览器表单** - 仍然需要CSRF token
-**用户登录** - 需要CSRF保护
-**敏感操作** - 需要额外验证
## 🔒 安全策略
### 分层防护
| 组件 | CSRF保护 | 其他保护措施 |
|------|----------|--------------|
| **API接口** | ❌ 豁免 | ✅ 登录验证、频率限制、参数验证 |
| **Web表单** | ✅ 启用 | ✅ CSRF token、表单验证 |
| **第三方回调** | ❌ 豁免 | ✅ 签名验证、IP白名单 |
### 详细配置
#### API安全措施
1. **登录验证**
```python
@api_bp.route('/licenses', methods=['POST'])
@require_login # 要求登录
def create_license():
# 需要管理员权限
```
2. **频率限制**
```python
@api_bp.route('/licenses/generate', methods=['POST'])
@rate_limit(limit=10, window=3600) # 每小时10次
def generate_license():
```
3. **参数验证**
```python
from flask_wtf import FlaskForm
from wtforms import IntegerField, StringField
class LicenseForm(FlaskForm):
product_id = StringField('产品ID', validators=[DataRequired()])
valid_days = IntegerField('有效天数', validators=[DataRequired()])
```
#### Web表单CSRF保护
1. **模板中自动包含CSRF token**
```html
<form method="POST">
{{ csrf_token() }} # Flask-WTF自动添加
</form>
```
2. **AJAX请求添加CSRF token**
```javascript
// 获取CSRF token
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
// AJAX请求头
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify(data)
});
```
## 🛡️ 安全检查
### 已实施的安全措施
- [x] API豁免CSRF当前配置
- [x] Web表单保持CSRF保护
- [x] API需要登录验证
- [x] API频率限制
- [x] 参数验证
- [x] CORS配置
- [x] 数据库约束
### 需要注意的安全点
1. **不要在API中信任客户端数据**
- 始终验证输入参数
- 使用参数化查询
- 实施白名单验证
2. **API访问控制**
- 确保所有API都需要认证
- 实施基于角色的访问控制
- 记录API访问日志
3. **第三方接口**
- 支付宝回调等需要单独处理
- 使用签名验证
- 限制IP白名单
## 🔧 配置选项
### 选项1: API豁免CSRF推荐
```python
# 当前配置 - API豁免CSRF
csrf.exempt(api_bp)
# 优点
- 简单可靠
- 不影响前端开发
- API有其他安全措施
# 适用场景
- 内部API系统
- 有完整认证机制
- 前后端分离架构
```
### 选项2: API启用CSRF
```python
# 启用API CSRF保护
# 需要修改前端代码
# 前端需要
1. 获取CSRF token
2. 在每个POST/PUT/DELETE请求中添加token
3. 处理token过期逻辑
# 缺点
- 复杂的前端实现
- 需要处理token刷新
- 可能影响API可用性
```
### 选项3: 混合模式
```python
# 仅对敏感API启用CSRF
from flask_wtf.csrf import csrf_exempt
# 部分API豁免
csrf.exempt(api_bp)
# 特定端点保护
@api_bp.route('/sensitive', methods=['POST'])
@csrf.protect() # 强制启用CSRF
def sensitive_operation():
```
## 🚀 验证配置
### 测试API豁免CSRF
```bash
# 直接调用API不需要CSRF token
curl -X POST http://localhost:5000/api/v1/licenses \
-H "Content-Type: application/json" \
-d '{"product_id": "test", "valid_days": 30}'
# 应该返回401未认证而不是400CSRF错误
```
### 测试Web表单CSRF
```html
<!-- 不包含CSRF token的表单应该被拒绝 -->
<form method="POST">
<input type="text" name="username">
<input type="password" name="password">
<!-- 没有{{ csrf_token() }} -->
<button type="submit">登录</button>
</form>
<!-- 返回400错误 -->
```
## 📊 风险评估
### 当前配置的安全性
| 风险类型 | 风险等级 | 缓解措施 |
|----------|----------|----------|
| CSRF攻击 | 🟡 中等 | API有认证机制 |
| XSS攻击 | 🟢 低 | 输入转义、输出编码 |
| SQL注入 | 🟢 低 | 参数化查询 |
| 会话劫持 | 🟡 中等 | HTTPS、Secure Cookie |
| API滥用 | 🟡 中等 | 频率限制、认证 |
### 建议的安全增强
1. **启用HTTPS** - 防止中间人攻击
2. **使用JWT token** - 替代session认证
3. **API签名验证** - 对敏感操作增加签名
4. **IP白名单** - 限制API访问来源
5. **审计日志** - 记录所有API调用
## 📞 支持与联系
### 常见问题
**Q: API返回400错误怎么办**
A: 检查是否恢复了`csrf.exempt(api_bp)`配置
**Q: 如何为特定API启用CSRF**
A: 使用`@csrf.protect()`装饰器
**Q: Web表单CSRF验证失败**
A: 确保模板包含`{{ csrf_token() }}`
**Q: AJAX请求如何添加CSRF token**
A: 从meta标签获取token并添加到请求头
### 工具脚本
- `scripts/fix_logging.py` - 修复日志问题
- `scripts/health_check.py` - 健康检查
### 相关文档
- [Flask-WTF CSRF文档](https://flask-wtf.readthedocs.io/)
- [OWASP CSRF指南](https://owasp.org/www-community/attacks/csrf)
- [系统优化报告](./SYSTEM_OPTIMIZATION_REPORT.md)
---
**更新时间**: 2025-12-12
**配置状态**: ✅ API豁免CSRFWeb表单保护