
Django 中 request.user 始终为 AnonymousUser,即使登录成功且 session 已存用户 ID,通常是因为自定义认证后端未被正确调用——根本原因在于 AUTHENTICATION_BACKENDS 配置顺序错误,导致 Django 优先使用默认 ModelBackend 而跳过了你的邮箱登录逻辑。
django 中 `request.user` 始终为 `anonymoususer`,即使登录成功且 session 已存用户 id,通常是因为自定义认证后端未被正确调用——根本原因在于 `authentication_backends` 配置顺序错误,导致 django 优先使用默认 `modelbackend` 而跳过了你的邮箱登录逻辑。
在 Django 认证体系中,request.user 并非直接从 session 读取用户对象,而是由 AuthenticationMiddleware 根据 AUTHENTICATION_BACKENDS 中注册的后端,按顺序调用每个后端的 get_user() 方法来重建用户实例。若所有后端均返回 None,则 request.user 默认为 AnonymousUser。
你已确认:
- authenticate() 在登录时能正确触发并返回用户;
- login(request, user) 成功将用户 ID 写入 session(request.session['_auth_user_id'] 存在且有效);
- 但后续请求中 request.user 仍为匿名用户。
这说明:get_user() 方法未被调用,或被调用但返回了 None。而根本原因几乎总是——你的 EmailBackend 在 AUTHENTICATION_BACKENDS 中位置靠后。
Django 的认证流程是严格顺序执行的:
- AuthenticationMiddleware 获取 session 中的 _auth_user_id;
- 依次遍历 AUTHENTICATION_BACKENDS 列表,对每个后端调用 backend.get_user(user_id);
- 只要某一个后端返回非 None 用户,立即停止并赋值给 request.user;若全部返回 None,则设为 AnonymousUser。
因此,如果你的配置类似:
# ❌ 错误:默认 ModelBackend 在前,它只认 username 字段(非 email),查不到用户即返回 None,
# 后续 EmailBackend 根本不会被执行
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'myapp.auth_backends.EmailBackend', # ← 永远没机会运行
]此时 ModelBackend.get_user() 会尝试用 user_id 查询标准 User 模型(或你自定义模型),但若模型字段/关系有误(如未继承 AbstractBaseUser 或 USERNAME_FIELD != 'email'),它可能静默失败并返回 None,而 Django 不会继续尝试下一个后端。
✅ 正确做法是:将自定义后端置于列表首位,确保它优先响应 get_user() 请求:
# ✅ 正确:自定义后端优先,能正确加载 email 用户
AUTHENTICATION_BACKENDS = [
'myapp.auth_backends.EmailBackend', # ← 必须第一
'django.contrib.auth.backends.ModelBackend', # 作为兜底(可选)
]同时,请确保你的自定义用户模型已正确定义 USERNAME_FIELD = 'email',例如:
# models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('Email is required')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'email' # ⚠️ 关键!告知 Django 主标识字段是 email
REQUIRED_FIELDS = []
objects = UserManager()此外,验证 EmailBackend.get_user() 是否真被调用:在方法内添加日志或断点,并访问任意需登录的视图(如 @login_required 页面),观察控制台输出。若无输出,说明后端未被轮询——100% 是配置顺序问题。
⚠️ 注意事项:
- AUTHENTICATION_BACKENDS 是元组或列表,必须显式声明,不可依赖默认值叠加;
- 修改后务必重启开发服务器(Django 不热重载 settings);
- 若项目含第三方认证(如 social-auth),需将其后端也按信任/优先级合理排序;
- get_user() 中的 user_id 是整数(主键值),请确保 User.objects.get(pk=user_id) 能成功查询(检查数据库是否存在、是否软删除等)。
总结:Django 的认证后端是“短路式”顺序执行,request.user 的加载完全依赖 get_user() 的链式调用结果。将自定义后端置于 AUTHENTICATION_BACKENDS 首位,是让 request.user 正常返回当前登录用户的关键前提。


















