Django登录接口重复请求出现CSRF缺失403错误求助
问题分析
你遇到的问题根源在于:登录接口调用login()函数后会创建Django Session并返回session cookie,后续请求携带该cookie时,DRF的SessionAuthentication会强制检查CSRF Token,但你的请求未携带该Token,因此触发403错误。虽然添加了@csrf_exempt,但DRF的认证逻辑优先级高于Django的CSRF豁免装饰器,导致豁免未生效。
解决方案
方案1:修改登录视图,禁用DRF的SessionAuthentication检查
通过添加DRF的装饰器,强制禁用该视图的Session认证和权限检查,确保@csrf_exempt生效:
from django.views.decorators.csrf import csrf_exempt from rest_framework.decorators import api_view, authentication_classes, permission_classes from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework import status from django.contrib.auth import authenticate, login @csrf_exempt @api_view(['POST']) @authentication_classes([]) # 禁用所有认证类,包括SessionAuthentication @permission_classes([AllowAny]) # 允许任何用户访问 def Userlogin1(request): print('login working') username = request.data.get('username') password = request.data.get('password') # 直接使用DRF的request对象,无需调用_request user = authenticate(request=request, username=username, password=password) if user is not None: login(request, user) return Response({'message': 'login successful.'}, status=status.HTTP_200_OK) return Response( {'error': 'Invalid credentials.', 'user': user, 'username': username, 'password': password}, status=status.HTTP_401_UNAUTHORIZED )
方案2:改用无状态认证(推荐)
放弃Django Session登录,使用DRF的TokenAuthentication或JWT,从根源避免Session cookie带来的CSRF问题:
步骤1:配置TokenAuthentication
在settings.py中添加如下配置:
INSTALLED_APPS = [ # ... 其他已安装应用 'rest_framework', 'rest_framework.authtoken', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], }
运行迁移生成Token数据表:
python manage.py migrate
步骤2:修改登录视图
from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework import status from django.contrib.auth import authenticate from rest_framework.authtoken.models import Token @api_view(['POST']) @permission_classes([AllowAny]) def Userlogin1(request): username = request.data.get('username') password = request.data.get('password') user = authenticate(username=username, password=password) if user is not None: # 获取或创建用户专属Token token, created = Token.objects.get_or_create(user=user) return Response( {'message': 'login successful.', 'token': token.key}, status=status.HTTP_200_OK ) return Response( {'error': 'Invalid credentials.'}, status=status.HTTP_401_UNAUTHORIZED )
后续请求只需在Header中携带Authorization: Token <你的token值>即可完成认证,无需处理CSRF。
方案3:保留Session但携带CSRF Token(不推荐用于登录接口)
如果必须保留Session登录,后续请求需要从Cookie中提取csrftoken值,放到请求Header的X-CSRFToken字段中。在Postman中可开启"Automatically send cookies",并手动添加X-CSRFToken Header,值为Cookie中的csrftoken内容。
内容的提问来源于stack exchange,提问作者Arslan Asghar
相关产品推荐
相关产品推荐

