前后端分离时Django CSRF防护需显式处理:服务端用@ensure_csrf_cookie确保Cookie写入,前端fetch/axios手动传X-CSRFToken头并配置credentials='same-origin',且必须启用SessionMiddleware。

前后端分离场景下,Django的CSRF防护默认行为会直接拦截所有AJAX POST/PUT/DELETE请求——除非你显式把csrftoken Cookie值塞进X-CSRFToken请求头,否则403是必然结果。
为什么前后端分离时{% csrf_token %}标签没用
这个模板标签只在服务端渲染HTML时起作用:它往<form>里插入一个<input type="hidden" name="csrfmiddlewaretoken" value="...">。但前后端分离时,前端(React/Vue)通常不走Django模板渲染,而是通过fetch或axios发JSON请求,模板根本没机会执行,{% csrf_token %}压根不会出现在HTML里。
常见错误现象:
– 页面加载后document.cookie里没有csrftoken;
– 用fetch发POST,浏览器开发者工具Network面板看到请求头没X-CSRFToken,响应直接403。
- 确保视图返回HTML页面时调用了
@ensure_csrf_cookie装饰器(比如首页或登录页),强制Django写入csrftokenCookie - 不要依赖
render()自动带上下文——前后端分离时,你很可能用的是TemplateView或直接返回空HTML,必须显式触发token生成 - 检查
CSRF_COOKIE_HTTPONLY = False(Django默认就是False,别手动改成True,否则JS读不到)
fetch和axios怎么正确传X-CSRFToken头
jQuery.ajax默认读取csrftoken Cookie并自动加头,但fetch和原生axios不会。你得自己读、自己塞。
立即学习“Python免费学习笔记(深入)”;
容易踩的坑:
– 用document.cookie.match(/csrftoken=([^;]+)/)正则解析,但Cookie里有多个字段时可能匹配错位;
– fetch默认credentials: 'omit',导致Cookie根本不上发,csrftoken读出来是null。
- 推荐把token存在
<meta name="csrf-token" content="{{ csrf_token }}">里,服务端渲染HTML时由Django注入,前端用document.querySelector('meta[name="csrf-token"]').getAttribute('content')安全读取 -
fetch必须设credentials: 'same-origin',否则连Cookie都拿不到 - axios全局配置:
axios.defaults.xsrfHeaderName = 'X-CSRFToken'; axios.defaults.xsrfCookieName = 'csrftoken';(注意不是xsrfTokenName)
CSRF_COOKIE_SAMESITE和HTTPS配置别踩坑
本地开发用HTTP时,CSRF_COOKIE_SAMESITE = 'None'会导致浏览器直接丢掉Cookie——因为SameSite=None强制要求Secure=True,即必须HTTPS。
生产环境若用Nginx反向代理,还要额外配CSRF_TRUSTED_ORIGINS,否则Referer校验失败也会403。
- 开发环境保持默认
CSRF_COOKIE_SAMESITE = 'Lax'即可,别改None - 生产环境必须设
CSRF_COOKIE_SECURE = True,否则HTTPS下Cookie不发送 - 如果前端域名是
app.example.com,后端Django要加CSRF_TRUSTED_ORIGINS = ['https://app.example.com'],不然Referer检查通不过
最常被忽略的一点:CSRF验证是否生效,和你用不用SessionAuthentication强相关。如果项目用TokenAuthentication且没启用SessionMiddleware,CsrfViewMiddleware压根不干活——它只对带session的请求校验。前后端分离项目若想用CSRF防护,必须保留session机制,不能全靠token。


















