django默认启用csrf防护但需确保令牌正确生成、分发、校验并绑定会话;flask默认不启用,须通过flask-wtf或手动实现,且令牌必须与会话强绑定、及时刷新与清除。

Python Web应用中CSRF漏洞不是“有没有开防护”的问题,而是“令牌是否正确生成、分发、校验、绑定会话”的问题。Django默认启用但可被绕过,Flask默认不启用且裸用request.form等于直接暴露敏感接口。
Django模板漏写{% csrf_token %}导致403
这是最常触发CSRF verification failed. Request aborted错误的原因,不是攻击发生,而是防护机制在拒绝非法请求。
- 必须把
{% csrf_token %}写在<form method="post"></form>标签内部,且不能在任何<input>之后——它要作为第一个子元素存在 - 如果用
render_to_response()(已弃用),RequestContext不会自动注入csrf_token变量,模板里{% csrf_token %}会展开为空字符串 - 动态JS插入
input(比如用document.createElement('input')塞进表单)无效:Django只认模板渲染时就存在的隐藏字段
Django中间件CsrfViewMiddleware配置错位或被禁用
即使模板写了{% csrf_token %},中间件没生效或顺序不对,整个机制就形同虚设。
- 检查
settings.py中MIDDLEWARE列表:'django.middleware.csrf.CsrfViewMiddleware'必须在'django.contrib.sessions.middleware.SessionMiddleware'之后、'django.contrib.auth.middleware.AuthenticationMiddleware'之前 - 若用了
django-cors-headers,'corsheaders.middleware.CorsMiddleware'必须排在CsrfViewMiddleware之前,否则预检请求可能干扰token读取 - 注释掉该中间件虽能消除报错,但等同于关闭防护——仅限本地调试,生产环境绝不可行
Flask未集成Flask-WTF或手动实现时令牌未绑定会话
Flask本身不提供CSRF防护,app.secret_key只是加密基础,不等于自动完成令牌生命周期管理。
- 必须调用
CSRFProtect(app)一次且仅一次;重复初始化CSRFProtect(app)不会覆盖已有实例,新对象无实际作用 - 手动实现时,
session['csrf_token']必须用secrets.token_urlsafe(32)生成(禁用random模块),且每次页面加载都要刷新,否则重放攻击可绕过 - 前端把
csrf_token拼进URL参数(如?token=xxx)或塞进API响应JSON体,都会导致泄露——令牌只能通过Cookie(HttpOnly=False; Secure=True; SameSite=Lax)或表单隐藏字段传递
CSRF Token与会话解耦是最大隐形风险
令牌再随机,只要没和会话强绑定、没随登出清除、有效期长于session过期时间,攻击者拿到旧session ID就能凑齐有效凭证。
- 用户登出时,必须显式调用
session.pop('csrf_token', None)并清空对应缓存(如Redis中关联的token) - 不要用全局静态token、不要复用同一token多次提交、不要让
set-cookie响应头缺失Secure(上线必须开)和SameSite=Lax - API接口若需CSRF防护,应避免返回
csrf_token字段到JSON响应体;前端JS读取后未清理,极易被XSS利用
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











