5.9 KiB
5.9 KiB
🔐 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豁免:
# 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安全措施
- 登录验证
@api_bp.route('/licenses', methods=['POST'])
@require_login # 要求登录
def create_license():
# 需要管理员权限
- 频率限制
@api_bp.route('/licenses/generate', methods=['POST'])
@rate_limit(limit=10, window=3600) # 每小时10次
def generate_license():
- 参数验证
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保护
- 模板中自动包含CSRF token
<form method="POST">
{{ csrf_token() }} # Flask-WTF自动添加
</form>
- AJAX请求添加CSRF token
// 获取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)
});
🛡️ 安全检查
已实施的安全措施
- API豁免CSRF(当前配置)
- Web表单保持CSRF保护
- API需要登录验证
- API频率限制
- 参数验证
- CORS配置
- 数据库约束
需要注意的安全点
-
不要在API中信任客户端数据
- 始终验证输入参数
- 使用参数化查询
- 实施白名单验证
-
API访问控制
- 确保所有API都需要认证
- 实施基于角色的访问控制
- 记录API访问日志
-
第三方接口
- 支付宝回调等需要单独处理
- 使用签名验证
- 限制IP白名单
🔧 配置选项
选项1: API豁免CSRF(推荐)
# 当前配置 - API豁免CSRF
csrf.exempt(api_bp)
# 优点
- 简单可靠
- 不影响前端开发
- API有其他安全措施
# 适用场景
- 内部API系统
- 有完整认证机制
- 前后端分离架构
选项2: API启用CSRF
# 启用API CSRF保护
# 需要修改前端代码
# 前端需要
1. 获取CSRF token
2. 在每个POST/PUT/DELETE请求中添加token
3. 处理token过期逻辑
# 缺点
- 复杂的前端实现
- 需要处理token刷新
- 可能影响API可用性
选项3: 混合模式
# 仅对敏感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
# 直接调用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(未认证)而不是400(CSRF错误)
测试Web表单CSRF
<!-- 不包含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滥用 | 🟡 中等 | 频率限制、认证 |
建议的安全增强
- 启用HTTPS - 防止中间人攻击
- 使用JWT token - 替代session认证
- API签名验证 - 对敏感操作增加签名
- IP白名单 - 限制API访问来源
- 审计日志 - 记录所有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- 健康检查
相关文档
更新时间: 2025-12-12 配置状态: ✅ API豁免CSRF,Web表单保护