95%的CSRF verification failed错误源于模板漏写{% csrf_token %}、CsrfViewMiddleware被注释或位置错误、AJAX请求未携带X-CSRFToken头;修复这三处即可解决。

直接说结论:95% 的 CSRF verification failed. Request aborted 错误,不是真被攻击了,而是模板漏了 {% csrf_token %}、中间件被注释、或 AJAX 请求没传 token —— 修复这三处,基本就稳了。
POST 表单里没加 {% csrf_token %}
这是最常见原因。Django 要求所有发往本域的 POST(以及 PUT、DELETE)请求必须携带有效 CSRF 令牌,而模板里漏掉这个标签,后端就收不到校验依据。
- 必须在
<form method="post"></form>内部、任意<input>之前插入{% csrf_token %} - 不能写成
{% csrf_token %}放在<form></form>外面,也不能只靠 JS 动态插入 DOM —— 模板渲染时就得存在 - 如果用的是
render()(而不是HttpResponse直接返回字符串),RequestContext会自动提供csrf_token变量,{% csrf_token %}才能展开 - 错误示例:
<form method="post"><input name="email"></form>→ 缺 token,必 403 - 正确示例:
<form method="post">{% csrf_token %}<input name="email"> </form>
settings.py 里 CsrfViewMiddleware 被注释或顺序错
django.middleware.csrf.CsrfViewMiddleware 是整个机制的执行者。它不在中间件链里,或者排在 SessionMiddleware 之后但又在 AuthenticationMiddleware 之前,token 就无法绑定 session,校验直接失败。
- 检查
MIDDLEWARE列表,确认'django.middleware.csrf.CsrfViewMiddleware'没被注释,且位置在SessionMiddleware之后、AuthenticationMiddleware之前 - 错误顺序:
SessionMiddleware→AuthenticationMiddleware→CsrfViewMiddleware→ 会导致 token 无法关联用户 session - 如果你用了
corsheaders,CorsMiddleware必须放在CsrfViewMiddleware之前,否则跨域预检可能干扰 token 读取 - 禁用它(比如注释掉)虽能绕过报错,但等于裸奔 —— 仅限本地调试,绝不可上生产
AJAX POST 请求没带 X-CSRFToken 头
前端用 fetch、axios 或 jQuery 发 POST,不会自动附带 cookie 里的 csrftoken,必须手动从 cookie 提取并塞进请求头。
立即学习“Python免费学习笔记(深入)”;
- 默认 cookie 名是
csrftoken,可通过CSRF_COOKIE_NAME配置修改,取值前先确认 - 不要把 token 放在 URL 参数或 request body 里(比如
data: {csrfmiddlewaretoken: 'xxx'}),既不安全也不被 Django 默认识别 - 标准做法是读 cookie 后设 header:
headers: {'X-CSRFToken': csrftoken},Django 通过CSRF_HEADER_NAME(默认HTTP_X_CSRFToken)读取 - 注意:若启用了
CSRF_USE_SESSIONS=True或CSRF_COOKIE_HTTPONLY=True,JS 就无法读 cookie → 此时得改用模板内联方式(如<script>window.CSRF_TOKEN = "{{ csrf_token }}";</script>)
局部豁免时用了 @csrf_exempt 却忘了风险
有些接口确实需要对外暴露(比如 webhook 接收第三方回调),这时用 @csrf_exempt 是合理选择,但必须清楚后果。
-
@csrf_exempt会完全跳过校验,不检查 token、不验证来源 —— 如果该视图还依赖登录态或操作敏感数据,就等于开了后门 - 更安全的替代是
@requires_csrf_token(保留 token 渲染但不强制校验)或@ensure_csrf_cookie(确保 cookie 发出,供前端读取),但它们不解决“无 token 提交”问题 - 真正需要豁免的场景极少;多数所谓“API 接口”其实应走 DRF 的
csrf_protect+ token header 流程,而非粗暴禁用 - 一旦用了
@csrf_exempt,务必在视图内部做额外鉴权,比如校验签名、IP 白名单、专用 API key
最容易被忽略的一点:CSRF 校验失败时,Django 默认返回 403 页面(DEBUG=True 时才显示详细提示)。很多人只盯着前端报错,却没看 network 面板里 response headers 是否有 Set-Cookie: csrftoken=... —— 如果连 cookie 都没下发,说明中间件根本没跑,问题一定出在 MIDDLEWARE 配置或请求路径匹配逻辑上。


















