已启用CSRF中间件的DRF CreateAPIView未校验CSRF令牌排查
核心根因解析
为什么加载了CSRF中间件却完全跳过校验
- 首先纠正一个普遍误区:只要把
django.middleware.csrf.CsrfViewMiddleware加到中间件列表,就会对所有POST请求强制做CSRF令牌校验。实际上这个中间件内置了明确的校验触发判断:只有当请求是通过Cookie携带的Session凭证完成身份认证时,才会执行CSRF令牌比对逻辑;其余场景直接放行。 - 你当前的DRF全局认证配置仅启用了两类认证方式:
RMS.authentication.JWTAuthentication、rest_framework.authentication.TokenAuthentication。这两类认证的身份解析完全由DRF在视图层完成,凭证从自定义请求头中读取,根本不依赖Django原生的Session机制建立登录态。 - 当请求经过
CsrfViewMiddleware时,中间件判断当前请求没有基于Session Cookie建立的有效登录态,直接跳过整个CSRF校验流程,根本不会去读取你前端携带的CSRF Cookie值、也不会对比请求里的CSRF令牌和Cookie值是否匹配。这就是你刻意修改CSRF Cookie取值也不会触发校验报错的原因——校验逻辑从一开始就没有被激活。 - 从DRF框架的设计逻辑看,仅当认证类使用
rest_framework.authentication.SessionAuthentication(也就是基于Cookie的Session认证)时,才会主动触发CSRF校验;其余基于请求头传凭证的认证类,从设计层面就不会关联CSRF校验流程。
为什么用令牌认证不需要开启CSRF校验
- CSRF攻击的成立必须满足两个核心条件:一是站点的身份认证凭证是存在Cookie里、可以被浏览器自动附带的;二是攻击者构造的跨站请求,可以自动携带该Cookie完成身份识别,让服务器误认为是合法用户发起的请求。
- 对于从请求头传递JWT/Token的认证方式,浏览器在发起跨站恶意请求时,受同源策略限制,根本不会自动附带自定义的
Authorization请求头。攻击者既拿不到用户的有效Token,也绕不开浏览器的跨域限制构造带凭证的请求,从根源上不存在CSRF攻击的成立基础,自然不需要额外的CSRF校验流程。 - 可以延伸一个联动逻辑:如果后续你给DRF全局配置加上了
SessionAuthentication(比如需要兼容传统服务端渲染页面的会话登录),此时CSRF校验就会自动生效。因为Session ID存在Cookie里,浏览器会自动携带,存在CSRF风险,DRF的Session认证类会在流程中主动触发CSRF校验,和中间件层的配置形成联动。
额外的配置提示
你当前的中间件顺序存在可优化点:corsheaders.middleware.CorsMiddleware需要放在django.middleware.common.CommonMiddleware之前,否则CORS跨域处理逻辑会出现异常,不过这个问题和当前CSRF校验跳过的现象没有直接关联。
内容的提问来源于stack exchange,提问作者Akash Tyagi
相关产品推荐
相关产品推荐

