Django Rest Framework POST请求鉴权异常:传Token仍提示未提供凭证
嘿,我之前也碰到过一模一样的情况——GET请求带着Token一切正常,偏偏POST接口就认不出认证凭证。咱们一步步来排查可能的原因:
1. 检查DRF认证类的配置顺序
如果你的settings.py里同时配置了SessionAuthentication和TokenAuthentication,DRF会按顺序尝试认证。浏览器发起的POST请求通常会自动带上Session相关的Cookie,这时候DRF可能优先走Session认证,忽略了你的Token。
解决方法:把TokenAuthentication放到认证类的最前面:
# settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', # 优先用Token认证 'rest_framework.authentication.SessionAuthentication', ], # 其他DRF配置... }
或者直接在你的POST视图里单独指定认证类,强制使用Token认证:
from rest_framework.authentication import TokenAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView class YourPostAPIView(APIView): authentication_classes = [TokenAuthentication] permission_classes = [IsAuthenticated] def post(self, request): # 你的业务逻辑 return Response({"status": "success"})
2. 确认Authorization请求头的格式完全正确
这是最容易踩坑的点!Authorization头的格式必须是 Token <你的token字符串>,注意Token后面有一个空格,绝对不能写成Token=<token>或者Bearer <token>(除非你用的是JWT)。
你可以用curl命令测试,确保格式正确:
curl -X POST http://your-api-domain/your-post-endpoint/ \ -H "Authorization: Token your_valid_token_here" \ -H "Content-Type: application/json" \ -d '{"example_key": "example_value"}'
3. 排查CSRF令牌的干扰
如果你的POST请求是从浏览器发起的(比如用AJAX或者表单),DRF的SessionAuthentication会强制要求CSRF令牌,但你用的是Token认证,这时候就会冲突。
解决方法:在你的POST视图里禁用CSRF检查。如果是类视图,可以用装饰器:
from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator @method_decorator(csrf_exempt, name='dispatch') class YourPostAPIView(APIView): authentication_classes = [TokenAuthentication] permission_classes = [IsAuthenticated] # ... 视图逻辑
如果是函数视图,直接加@csrf_exempt装饰器:
from django.views.decorators.csrf import csrf_exempt from rest_framework.decorators import api_view, authentication_classes, permission_classes from rest_framework.authentication import TokenAuthentication from rest_framework.permissions import IsAuthenticated @csrf_exempt @api_view(['POST']) @authentication_classes([TokenAuthentication]) @permission_classes([IsAuthenticated]) def your_post_view(request): # 业务逻辑 return Response({"status": "success"})
4. 验证Token本身的有效性
虽然GET请求能用,但还是要确认Token是否真的有效:
- 登录Django Admin,检查
Tokens模型里对应的Token是否存在,关联的用户是否正确 - 如果你的项目配置了Token过期机制,确认Token还在有效期内
5. 确认请求头确实被后端接收到
有时候前端框架(比如Axios)的请求拦截器可能没正确设置Authorization头,或者跨域配置没允许Authorization头通过。你可以在视图里打印请求头,确认Token是否传到后端:
def post(self, request): # 打印所有请求头,检查HTTP_AUTHORIZATION是否存在 print(request.META.get('HTTP_AUTHORIZATION')) # 其他逻辑
如果以上方法都试过还是解决不了,可以把你的视图代码、DRF配置以及前端请求的代码贴出来,我再帮你进一步排查~
内容的提问来源于stack exchange,提问作者William Zimmermann

