为何Set-Cookie头中无CSRF Token?Django DRF接口问题咨询
我来帮你拆解下这个问题——你遇到的情况其实和Django及DRF的CSRF防护机制默认逻辑有关,之前我也碰到过类似的坑。
核心原因
Django的CSRF中间件默认只会在返回HTML内容的GET请求中自动设置Set-Cookie头(比如Django自带的模板页面),而DRF的APIView返回的是JSON格式响应,默认不会主动触发CSRF Cookie的生成和设置。哪怕Postman里之前存过CSRF Cookie,一旦过期或被清除,后续的GET请求就没法再获取新的Cookie了。
另外,DRF的SessionAuthentication虽然依赖CSRF验证,但它不会在未登录的GET请求中自动生成CSRF Cookie,只有当用户通过session登录后,相关逻辑才会触发。
解决办法
1. 在GET方法中手动触发CSRF Cookie生成
你可以在get方法里调用Django提供的get_token()函数,这个函数会自动生成CSRF Token并将其添加到响应的Set-Cookie头中。修改你的代码如下:
from django.middleware.csrf import get_token from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class HelloView(APIView): def get(self, request): # 手动触发CSRF Cookie生成 get_token(request) clients = client.objects.all() serializer = ClientSerializerAPIView(clients, many=True) return Response(serializer.data) def post(self, request): serializer = ClientSerializerAPIView(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
注意:我把你post方法里的HTTP_404_NOT_FOUND改成了HTTP_400_BAD_REQUEST,因为参数验证失败应该返回400(请求错误)而不是404(资源不存在),这是更规范的REST接口做法。
2. 确认CSRF中间件已启用
检查你的settings.py文件,确保MIDDLEWARE列表中包含'django.middleware.csrf.CsrfViewMiddleware',这是CSRF Cookie生成的基础:
MIDDLEWARE = [ # 其他中间件... 'django.middleware.csrf.CsrfViewMiddleware', # 其他中间件... ]
3. 测试验证
修改代码后,用Postman重新发送GET请求,你就能在响应头里看到Set-Cookie字段,里面包含新的CSRF Token了。之后发送POST请求时,记得把这个Token放到X-CSRFToken请求头里,或者作为表单数据提交,这样就能通过DRF的CSRF验证了。
内容的提问来源于stack exchange,提问作者parsa

