自定义Django认证后端异常:登录后仍跳转至登录页
request.user.is_authenticated无效问题 我实现了一个讲师登录用的自定义Django认证后端TutorAuthBackend,认证后端能正常返回有效用户对象,但使用@login_required装饰器时,检测到request.user.is_authenticated为None,导致无限登录循环。我尝试打印跨请求的session_key,结果一致;也调整了SESSION_COOKIE_AGE为7天,显式指定SESSION_ENGINE为django.contrib.sessions.backends.db,但问题仍未解决。在仪表盘视图中,request.user显示为AnonymousUser,request.user.is_authenticated()返回false。
相关代码:
from django.contrib.auth.backends import ModelBackend from django.core.exceptions import ValidationError from django.core.validators import validate_email from django.contrib.auth import login from django.contrib import messages from django.shortcuts import render, redirect from .models import Tutor class TutorAuthBackend(ModelBackend): def authenticate(self, request, username_or_email=None, password=None, **kwargs): print(f"Attempting to authenticate: {username_or_email}") try: validate_email(username_or_email) is_valid_email_format = True except ValidationError: is_valid_email_format = False auth_type = 'email__iexact' if is_valid_email_format else 'username__iexact' auth_param = {auth_type: username_or_email} try: tutor = Tutor.objects.get(**auth_param) if tutor.check_password(password): print(f"Authenticated: {tutor}") return tutor except Tutor.DoesNotExist: pass return None def get_user(self, user_id): """ Returns the tutor object using the given user_id. """ try: return Tutor.objects.get(pk=user_id) except Tutor.DoesNotExist: return None def tutor_login(request): if request.method == 'POST': username_or_email = request.POST.get('username_or_email') password = request.POST.get('password') tutor = TutorAuthBackend().authenticate(request, username_or_email=username_or_email, password=password) if tutor: login(request, tutor, backend='tutor.backends.TutorAuthBackend') messages.success(request, "You're Logged In") if tutor.profile_picture: print("Profile Picture:", tutor.profile_picture.url) return redirect('tutor_dashboard', tutor_id=tutor.id) return redirect('tutor_profile') else: tutor_exists = Tutor.objects.filter(username=username_or_email).exists() if tutor_exists: messages.error(request, 'Incorrect Password') else: messages.error(request, 'User Not Found') return render(request, 'tutor/tutor_login.html', context={'username_or_email': username_or_email}) else: return render(request, 'tutor/tutor_login.html')
排查与解决方法
1. 确认自定义用户模型配置
如果Tutor是作为自定义用户模型使用,必须:
- 继承
AbstractBaseUser和PermissionsMixin - 在
settings.py中设置AUTH_USER_MODEL = 'tutor.Tutor'(替换为你的app名和模型名)
如果Tutor只是普通模型而非用户模型,Django认证系统无法将其识别为合法用户,会导致登录后仍为AnonymousUser。
2. 添加认证后端到配置
在settings.py中配置认证后端列表,确保你的自定义后端被包含:
AUTHENTICATION_BACKENDS = [ 'tutor.backends.TutorAuthBackend', 'django.contrib.auth.backends.ModelBackend', # 可选,保留默认后端兼容 ]
3. 修正is_authenticated的调用方式
Django 1.10+版本中,is_authenticated是只读属性,不是方法。原代码中request.user.is_authenticated()的写法会返回False(因为调用了不存在的方法),正确写法是request.user.is_authenticated(无括号)。
4. 验证后端路径正确性
确保login函数中指定的后端路径'tutor.backends.TutorAuthBackend'与实际文件路径一致。比如你的后端文件是tutor/backends.py,这个路径就是正确的;如果文件结构不同,需对应调整。
5. 检查用户模型必要属性
自定义用户模型Tutor必须包含:
USERNAME_FIELD(指定唯一标识字段,比如username或email)is_active属性(默认应为True,否则用户会被视为无效)- 继承
AbstractBaseUser会自动获得check_password等必要方法
6. 调试会话状态
在登录视图和仪表盘视图中添加调试代码,确认会话和用户身份:
# 登录视图login后添加 print(f"登录后用户: {request.user}, 认证状态: {request.user.is_authenticated}") print(f"会话key: {request.session.session_key}") # 仪表盘视图开头添加 print(f"仪表盘请求用户: {request.user}, 认证状态: {request.user.is_authenticated}") print(f"会话key: {request.session.session_key}")
如果会话key一致但用户身份未被识别,基本可以确定是用户模型未被Django认证系统正确识别。
内容的提问来源于stack exchange,提问作者Chime Kingsley

