Django默认启用CsrfViewMiddleware防护CSRF攻击,但POST表单必须添加{% csrf_token %}生成令牌,AJAX请求需从cookie提取csrftoken并设X-CSRFToken请求头,否则403拒绝;禁用防护或配置不当将导致安全失效。

默认启用的 CsrfViewMiddleware 已经为你挡下了绝大多数 CSRF 攻击,但一旦漏掉关键环节(比如模板没插 {% csrf_token %}、AJAX 请求没传 header),整个防护就形同虚设。
为什么 POST 表单必须加 {% csrf_token %}
Django 的 CSRF 验证只对“不安全方法”(如 POST、PUT、DELETE)生效,且仅当请求携带了匹配的 token 才放行。这个 token 不是固定值,它由 session 或 cookie 生成,绑定当前用户和浏览器上下文。
- 漏写
{% csrf_token %}→ 请求被403 Forbidden拦截,错误信息是CSRF verification failed. Request aborted. - 写在指向外部 URL 的表单里 → token 泄露到第三方服务器,等于把钥匙交给攻击者
- 用
render()渲染模板但没传request→{% csrf_token %}渲染为空,token 根本不生成
如何让 AJAX POST 请求通过 CSRF 验证
直接在 data 中塞 csrfmiddlewaretoken 字段太容易遗漏,推荐用 header 方式统一处理。
- 前端先从
document.cookie提取csrftoken(注意:Django 默认用csrftoken名称,不是csrf_token) - 所有 AJAX POST/PUT/DELETE 请求都加 header:
X-CSRFToken: <提取到的值> - 确保视图没被标记为
@csrf_exempt,否则中间件直接跳过验证 - 如果启用了
CSRF_USE_SESSIONS = True,token 会从 session 而非 cookie 读取,前端无法直接获取 —— 这时必须后端提供 API 返回 token
哪些情况会绕过 CSRF 验证(以及为什么危险)
@csrf_exempt 是唯一能关闭单个视图 CSRF 检查的装饰器,但它不是“可选开关”,而是“紧急逃生门”。
立即学习“Python免费学习笔记(深入)”;
- 给登录接口加
@csrf_exempt→ 登录前用户无 session,但攻击者可伪造登录请求,批量撞库或重放凭证 - 全局禁用
CsrfViewMiddleware→ 所有 POST 视图裸奔,连管理后台的删除按钮都可能被恶意页面触发 - 子域名共用主站 cookie 且未设置
CSRF_COOKIE_DOMAIN→ 攻击者控制evil.example.com可向app.example.com发起带合法 cookie 的请求
最常被忽略的是 referer 检查:HTTPS 环境下,Django 会校验请求头 Referer 是否与当前域同源。如果你用了反向代理或前端路由(如 Vue Router history 模式),referer 可能丢失或不匹配,导致合法请求被误拒 —— 这时候要调 CSRF_TRUSTED_ORIGINS,而不是关防护。


















