Django自定义后端登录异常:认证成功但未实际登录
Django自定义认证后端登录成功但用户未实际登录的修复方案
你的问题出在三个核心地方:自定义User模型的配置缺失、认证后端方法缩进错误、密码字段重复定义导致验证失效,以下是分步修复:
1. 修正自定义User模型
继承AbstractBaseUser必须指定USERNAME_FIELD(用于认证的唯一标识字段),且不需要重复定义password、last_login这些父类已有的字段——你自己定义的password是明文存储,会导致check_password验证永远失败。另外last_login需要用DateTimeField而非DateField,否则Django更新登录时间时会出错。
修正后的models.py:
from django.contrib.auth.models import AbstractBaseUser class User(AbstractBaseUser): id = models.AutoField(primary_key=True) username = models.TextField(unique=True) # 认证字段需保证唯一 real_name = models.TextField() email = models.TextField() description = models.TextField() created_at = models.DateField(auto_now_add=True) # 自动设置创建时间 is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True) # 必须指定的认证字段 USERNAME_FIELD = 'username' # 超级用户创建时必填字段(可选配置) REQUIRED_FIELDS = ['email'] class Meta: managed = False db_table = 'user' def __str__(self) -> str: return self.username
2. 修复认证后端的方法缩进
你的UserBackend中get_user方法缩进错误,被嵌套在authenticate方法内部,导致Django无法调用该方法验证登录状态。需要将get_user移到authenticate同级:
修正后的backends.py:
from django.contrib.auth.backends import ModelBackend from .models import User class UserBackend(ModelBackend): def authenticate(self, **kwargs): username = kwargs.get('username') password = kwargs.get('password') if not username or not password: return None try: user_ = User.objects.get(username=username) if user_.check_password(password): return user_ except User.DoesNotExist: return None # 移到authenticate方法外部,保持同级缩进 def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
3. 优化视图中的认证逻辑
不需要手动实例化UserBackend,直接使用Django内置的auth.authenticate,前提是在settings.py中配置你的认证后端:
# settings.py添加配置 AUTHENTICATION_BACKENDS = [ 'core.backends.UserBackend', ]
修正后的signin视图:
from django.contrib.auth import authenticate, login from django.shortcuts import redirect, render from django.contrib import messages def signin(request): if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] # 使用内置authenticate,自动调用配置的后端 user = authenticate(request, username=username, password=password) if user is not None: login(request, user) print('Logged In') # 优先跳转到next参数,否则回到首页 next_url = request.GET.get('next', '/') return redirect(next_url) else: messages.info(request, 'Invalid Username or Password! Try again') return redirect("signin") return render(request,'signin.html')
验证步骤
- 确保PostgreSQL中的
user表密码字段是Django加密后的格式(如果之前是明文,需通过Django shell执行user.set_password('新密码')后保存) - 重启Django服务,重新测试登录
内容的提问来源于stack exchange,提问作者Dirky
相关产品推荐
相关产品推荐

