Django跨App用Mixin获取登录用户返回AnonymousUser问题求助
DRF登录后request.user返回AnonymousUser问题修复
问题表现
基于Django REST Framework + React前后端分离架构开发时,调用原生登录接口完成登录后,自定义权限Mixin中读取request.user始终返回匿名用户,无法获取已登录用户信息。
核心根因
- 自定义
storekeeperMixin的dispatch方法未调用父类实现、未返回响应,DRF完整请求处理链路被截断,内置认证逻辑根本没有执行,用户信息不会被加载到request对象中。 - DRF默认未开启SessionAuthentication认证类,无法识别Django原生
login()方法写入的session登录态。 - 前端跨域请求未配置携带凭证,登录下发的sessionid、csrftoken cookie不会被浏览器保存,后续请求不会携带认证信息传给后端。
- 跨域配置错误、CSRF cookie未正常下发,导致认证请求被拦截。
修复步骤
1. 修复自定义Mixin逻辑
补全dispatch方法的父类调用和响应返回,确保请求走完完整认证流程:
class storekeeperMixin(): def dispatch(self, request, *args, **kwargs): # 调用父类dispatch,执行DRF内置的认证、权限、请求处理逻辑 response = super().dispatch(request, *args, **kwargs) # 流程走完后再读取用户信息,此时已完成认证加载 print('****************************' + str(request.user.username)) # 必须返回响应,否则接口无法正常返回数据 return response class driverapi(storekeeperMixin,viewsets.ViewSet): def get(self,request,format=None): # 注意原代码笔误:object -> objects,Django模型默认管理器为objects driverslist = driver.objects.all() # 注意序列化器类名、变量名拼写和实际定义对齐 serializer = OBJdriver(driverslist, many=True) return Response(serializer.data)
2. 配置DRF默认认证类
在项目settings.py中添加DRF配置,开启session认证对齐Django原生登录逻辑:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', ], # 接口默认需要登录才能访问,可按需调整 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] }
3. 补全登录接口装饰器
给登录接口添加请求方法限制、CSRF cookie下发装饰器,确保登录态cookie正常返回给前端:
import json from django.contrib.auth import authenticate, login, logout from django.http import JsonResponse from django.middleware.csrf import get_token from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_POST @require_POST @ensure_csrf_cookie def login_view(request): data = json.loads(request.body) username = data.get('username') password = data.get('password') if username is None or password is None: return JsonResponse({'detail': '请提供用户名和密码'}, status=400) user = authenticate(username=username, password=password) if user is None: return JsonResponse({'detail': '用户名或密码错误'}, status=400) login(request, user) return JsonResponse({'detail': '登录成功'}) # 前端初始化时可调用该接口获取CSRF cookie @ensure_csrf_cookie def get_csrf_token(request): return JsonResponse({'csrfToken': get_token(request)})
4. 前端请求配置
所有发往后端的请求必须开启携带凭证配置,确保cookie能跨域正常传输:
- 若使用axios,添加全局配置:
import axios from 'axios' // 跨域请求携带cookie axios.defaults.withCredentials = true // 自动从cookie读取CSRF token放到请求头,避免403报错 axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = 'X-CSRFToken'
- 若使用原生fetch,每个请求添加credentials配置:
fetch('/api/your-endpoint/', { credentials: 'include', // 其余请求配置:method、headers、body等 })
5. 跨域配置检查
前后端端口不一致时,正确配置django-cors-headers:
- 安装依赖后在
INSTALLED_APPS中添加corsheaders - 在
MIDDLEWARE最顶部添加corsheaders.middleware.CorsMiddleware - 在
settings.py中添加配置:
# 替换为前端实际部署地址,生产环境不要开启全源允许 CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", ] # 允许跨域携带凭证 CORS_ALLOW_CREDENTIALS = True
注意:禁止同时开启
CORS_ALLOW_ALL_ORIGINS = True和CORS_ALLOW_CREDENTIALS = True,浏览器会直接拦截该类响应。
内容的提问来源于stack exchange,提问作者misaq yarian
相关产品推荐
相关产品推荐

