CsrfViewMiddleware与enforce_csrf的区别及仅用中间件处理CSRF是否可行?
关于Django中CSRF令牌重复校验的问题解答
是的,仅通过CsrfViewMiddleware中间件就足够完成CSRF令牌的发放与校验,不需要在自定义认证流程中重复执行CSRF校验,你的重复校验逻辑正是导致Cookie与响应中csrf_token值不一致的原因。
问题分析
中间件的核心作用:
CsrfViewMiddleware已经自动覆盖了CSRF防护的全流程:- 为首次请求生成CSRF令牌并写入Cookie
- 对POST/PUT/DELETE等不安全HTTP方法的请求自动校验令牌合法性
- 配合你配置的
CSRF_COOKIE_SECURE、CSRF_COOKIE_SAMESITE等参数完成安全防护
重复校验的冲突:你在自定义JWT认证中额外添加的
enforce_csrf校验,相当于重复触发了一次CSRF令牌的校验/生成逻辑,这会导致系统多次生成令牌或者校验逻辑冲突,最终出现Cookie与响应头中令牌不一致的问题。
解决方案
移除自定义认证中的重复校验代码
修改authenticate.py,删除enforce_csrf函数及相关调用,保留纯JWT认证逻辑:from rest_framework_simplejwt import authentication as jwt_authentication from django.conf import settings from rest_framework import exceptions as rest_exceptions class CustomAuthentication(jwt_authentication.JWTAuthentication): def authenticate(self, request): header = self.get_header(request) if header is None: raw_token = request.COOKIES.get(settings.SIMPLE_JWT['AUTH_COOKIE']) or None else: raw_token = self.get_raw_token(header) if raw_token is None: return None validated_token = self.get_validated_token(raw_token) # 移除enforce_csrf(request)调用 return self.get_user(validated_token), validated_token保留loginView的响应头设置
由于你设置了CSRF_COOKIE_HTTPONLY = True,前端无法通过JS读取CSRF Cookie,因此loginView中通过响应头返回X-CSRFToken的写法是正确的,无需修改:response["X-CSRFToken"] = request.COOKIES.get("csrftoken")修正settings中的参数拼写错误
你原配置中的CSRF_TESTED_ORIGINS是拼写错误,正确参数名为CSRF_TRUSTED_ORIGINS,修正后的配置如下:CSRF_COOKIE_SECURE = True # 仅在HTTPS环境下启用CSRF Cookie CSRF_COOKIE_HTTPONLY = True # CSRF Cookie设为HttpOnly,防止XSS窃取 CSRF_TRUSTED_ORIGINS = [ "http://localhost:8000" ] CSRF_COOKIE_SAMESITE = "Lax" # 跨站请求防护 MIDDLEWARE = [ ... 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', ... ]
内容的提问来源于stack exchange,提问作者dayday
相关产品推荐
相关产品推荐

