如何为Django前端登录获取csrfToken?仍遇403验证失败
解决DRF登录接口CSRF校验失败问题
场景1:使用Session认证(需处理CSRF)
如果你的项目依赖Django Session管理用户会话,按以下步骤排查修复:
1. 正确获取并携带CSRF令牌
你写的CSRF获取视图没问题,但前端请求该接口时必须携带凭证(Cookie):
- Axios示例:
axios.get('/csrf/', { withCredentials: true }) - Fetch示例:
fetch('/csrf/', { credentials: 'include' })
只有这样,Django才会在响应Cookie中写入csrftoken。
- Axios示例:
登录请求时,不要把
csrfmiddlewaretoken放在请求体,而是从Cookie中读取csrftoken值,添加到请求头:- 请求头字段:
X-CSRFToken: <从Cookie读取的token值> - 同时登录请求也要携带凭证(Axios加
withCredentials: true,Fetch加credentials: 'include')
- 请求头字段:
2. 确保登录视图是DRF风格
不要直接用Django自带的LoginView,改用DRF的APIView或@api_view装饰器编写:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.contrib.auth import authenticate, login class LoginView(APIView): def post(self, request): username = request.data.get('username') password = request.data.get('password') user = authenticate(request, username=username, password=password) if user: login(request, user) return Response({'msg': '登录成功'}, status=status.HTTP_200_OK) return Response({'error': '用户名或密码错误'}, status=status.HTTP_401_UNAUTHORIZED)
常见错误排查
- 前端是否禁用了Cookie?跨域场景下,后端还需配置
CORS_ALLOW_CREDENTIALS = True允许携带凭证。 - 浏览器开发者工具的Application面板中,是否存在
csrftokenCookie?
场景2:改用Token/JWT认证(无需CSRF校验)
前后端分离项目更推荐无状态的Token认证,彻底避开CSRF问题:
1. 配置Token认证
在settings.py中添加:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], }
2. 生成Token表
执行迁移命令:
python manage.py migrate
3. 编写登录视图返回Token
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.contrib.auth import authenticate from rest_framework.authtoken.models import Token class LoginView(APIView): # 禁用CSRF校验,因为用Token认证 authentication_classes = [] permission_classes = [] def post(self, request): username = request.data.get('username') password = request.data.get('password') user = authenticate(username=username, password=password) if user: token, _ = Token.objects.get_or_create(user=user) return Response({'token': token.key}, status=status.HTTP_200_OK) return Response({'error': '用户名或密码错误'}, status=status.HTTP_401_UNAUTHORIZED)
后续请求使用Token
后续接口请求时,在请求头添加:
Authorization: Token <你的Token值>
内容的提问来源于stack exchange,提问作者Peter Kronenberg
相关产品推荐
相关产品推荐

