使用TokenAuthentication的DRF公共APIView出现CSRF token缺失错误
问题根因定位
- 首先澄清两个常见认知误区:
- DRF的
permission_classes控制的是接口访问权限,和CSRF校验逻辑完全无关,空列表仅代表不需要权限校验,不会关闭CSRF校验。 - 「DRF仅在使用SessionAuthentication时触发CSRF校验」的规则是DRF层面的校验逻辑,而你Django全局中间件中还保留了
django.middleware.csrf.CsrfViewMiddleware,这个Django原生的全局CSRF校验优先级高于DRF的认证逻辑,只要满足两个条件就会触发:请求为POST/PUT等非安全方法、请求中携带了对应域名的session cookie。由于你前后端部署在同一域名下,用户只要之前在站点产生过session(比如登录过其他功能),前端发请求就会自动携带session cookie,触发全局CSRF校验,和你是否使用JWT认证没有关联。
- DRF的
- 你添加
csrf_exempt无效的原因:DRF的APIView不能直接给视图方法加csrf_exempt装饰器,要么加在路由的as_view()调用上,要么用method_decorator包装后加在视图类上。
解决方案
你可以根据自己的技术选型二选一:
方案1:完全移除CSRF相关配置(适配纯JWT认证场景)
如果你全程使用JWT做身份认证,完全不需要Django的Session体系,直接做两个修改即可:
- 从
MIDDLEWARE配置中删除django.middleware.csrf.CsrfViewMiddleware和django.contrib.sessions.middleware.SessionMiddleware两个中间件 - 所有
SESSION_*、CSRF_*开头的配置项全部可以删除,无需保留
该方案最彻底,完全适配纯JWT接口服务的技术选型,不会再产生CSRF相关报错。
方案2:保留Session体系,仅给指定视图豁免CSRF
如果你后续需要使用Session相关功能,不想全局移除CSRF中间件,可正确配置当前视图的CSRF豁免:
第一种方式,修改路由配置:
from django.views.decorators.csrf import csrf_exempt urlpatterns = [ ... path('recaptcha_verify/', csrf_exempt(RecaptchaVerifyView.as_view()), name='recaptcha_verify'), ... ]
第二种方式,给视图类加装饰器:
from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt @method_decorator(csrf_exempt, name='dispatch') class RecaptchaVerifyView(APIView): permission_classes = [] serializer_class = ReCaptchaSerializer # 剩余原有逻辑保持不变
其他疑问说明
你另一个公开登录视图没有触发报错的原因,大概率是登录请求触发时用户还没有产生session cookie,全局CSRF中间件不会触发校验;登录完成后生成了session cookie,再访问其他未做CSRF豁免的POST接口就会触发报错。
内容的提问来源于stack exchange,提问作者Beinje
相关产品推荐
相关产品推荐

