Django CSRF防护默认启用但需手动配合:表单加{% csrf_token %}、AJAX传X-CSRFToken头、注意SameSite策略与HTTPS要求,否则403拒绝。

CSRF中间件默认就开着,但没加csrf_token模板标签等于白搭
Django从1.2起默认启用django.middleware.csrf.CsrfViewMiddleware,但它只负责校验请求,不自动注入防护标记。你得在每个POST/PUT/DELETE表单里手动加{% csrf_token %},否则浏览器发请求时没token,中间件直接403。
- 所有用
POST提交的HTML表单(包括Django Admin、自定义Form)都必须包含{% csrf_token %} - AJAX请求要手动读取
csrftokenCookie,并在请求头里带上X-CSRFToken字段 - 如果用了
@csrf_exempt装饰器,就绕过了整个防护——确认这是你真实需要的,不是图省事
为什么fetch发POST总被拒,而jQuery.ajax却没事
因为jQuery默认从Cookie读csrftoken并自动设请求头,fetch不会。Django的CSRF中间件检查两个地方:表单里的csrfmiddlewaretoken字段,或请求头中的X-CSRFToken。没设就拒绝。
-
fetch需显式读取Cookie:document.cookie.match(/csrftoken=([^;]+)/)[1],再传给headers: {'X-CSRFToken': token} - 更稳妥的做法是把token存在
<meta>标签里,比如<meta name="csrf-token" content="{{ csrf_token }}">,避免正则解析Cookie出错 - 注意
SameSite=Lax的Cookie策略可能影响跨站请求下的token读取,开发环境建议检查浏览器开发者工具的Application → Cookies
CsrfViewMiddleware对静态文件和API接口的处理逻辑
中间件只拦截有CSRF敏感方法(POST/PUT/PATCH/DELETE)且带会话的请求。它不拦GET、HEAD、OPTIONS,也不拦没SessionMiddleware的请求——比如纯API服务若用Token认证、没启session,那这个中间件根本不起作用。
提供使用 django-unfold (v0.56+) 构建高级 Django 管理界面的专业指导。当用户提及 django-unfold、unfold admin 等内容时使用此技能。
- 静态文件(
/static/、/media/)走StaticFilesHandler或Nginx,绕过Django中间件链,完全不受CSRF限制 - DRF项目若用
TokenAuthentication且没启用session,CsrfViewMiddleware不会校验任何请求;要用SessionAuthentication才生效 - 如果视图加了
@ensure_csrf_cookie,会强制写入csrftokenCookie,哪怕当前请求是GET——适合前后端分离时提前“种”token
本地开发HTTPS缺失导致SameSite=None失效
Django 3.1+默认设CSRF_COOKIE_SAMESITE = 'Lax',这是安全的默认值。但如果你在本地用HTTP开发,又试图设'None',浏览器会直接丢掉这个Cookie——因为SameSite=None必须搭配Secure=True(即HTTPS)。
立即学习“Python免费学习笔记(深入)”;
- 开发时别强行改
CSRF_COOKIE_SAMESITE = 'None',保持默认'Lax'即可 - 上线前确保Nginx或负载均衡器终止HTTPS,并设置
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'),否则Django不知道该发Secure Cookie - 检查响应头:
Set-Cookie里是否含Secure; SameSite=Lax,没有就说明配置没生效
{% csrf_token %}、AJAX没传头、本地HTTP硬配SameSite=None、或者误以为关掉中间件能“简化开发”。这些点不盯住,光看文档里的“已启用”三个字没用。

















