Django REST API JWT认证遇CSRF验证失败403错误求助
你遇到的这个CSRF验证失败问题,核心原因是你的认证配置里同时启用了SessionAuthentication和JWT认证:当Postman的请求携带了Django的session cookie时(比如之前访问过Django admin后台留下的),DRF会优先触发SessionAuthentication的CSRF检查,但Postman并没有携带对应的CSRF令牌,所以返回403错误。
下面给你几个可行的解决方案,按推荐程度排序:
方案一:调整认证类顺序,优先使用JWT认证
在你的REST_FRAMEWORK配置里,把JSONWebTokenAuthentication放在最前面,这样DRF会优先尝试用JWT令牌认证,只有当JWT认证失败时才会 fallback 到其他认证方式,从而跳过Session的CSRF检查:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 移到最前面 'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
方案二:移除不必要的SessionAuthentication(推荐纯API场景)
如果你的服务是纯前后端分离的API,不需要支持Session认证(比如不需要通过浏览器访问Django admin),可以直接从DEFAULT_AUTHENTICATION_CLASSES里移除SessionAuthentication,从根源上避免CSRF问题:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.BasicAuthentication', # 移除SessionAuthentication ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
方案三:针对API视图禁用CSRF验证
如果必须保留SessionAuthentication,可以单独给API视图禁用CSRF检查:
- 对于函数视图,使用
@csrf_exempt装饰器:
from django.views.decorators.csrf import csrf_exempt from rest_framework.decorators import api_view @csrf_exempt @api_view(['POST']) def testspsearch(request): # 你的视图逻辑 pass
- 对于类视图,重写
dispatch方法并添加装饰器:
from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator from rest_framework.views import APIView @method_decorator(csrf_exempt, name='dispatch') class TestSpSearchView(APIView): def post(self, request): # 你的视图逻辑 pass
方案四:清除Postman中的Session Cookie
如果只是测试阶段的临时问题,可以手动清除Postman中127.0.0.1:8000域名下的Cookie,这样请求就不会携带session cookie,DRF就不会触发CSRF检查:
- 打开Postman的请求标签页,点击"Headers"下方的"Cookies"按钮
- 在弹出窗口中找到
127.0.0.1:8000的所有Cookie并删除 - 重新发送携带Bearer令牌的请求
最后再检查下Postman的请求头格式:确保Authorization头是Bearer <你的JWT令牌>(注意Bearer和令牌之间有一个空格),你的配置里JWT_AUTH_HEADER_PREFIX支持JWT和Bearer两种前缀,格式不能出错。
内容的提问来源于stack exchange,提问作者Bharath R S

