You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义用户模型与认证功能失效问题求助

Django自定义用户模型认证故障排查

问题背景

我是Django初学者,当前项目不需要is_staff、is_superuser、is_admin字段,因此自定义了用户模型,但认证功能无法正常工作。使用的是遗留数据库,通过python manage.py inspectdb生成模型,未修改字段名与表名,可接受通过Shell创建用户。

相关配置与代码

settings.py

AUTH_USER_MODEL = 'accounts.Usermanagement'

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'accounts.backends.EmailAuthBackend',
]

backends.py

#backends.py

# from django.contrib.auth.models import User
from django.contrib.auth.hashers import check_password
from django.contrib.auth import get_user_model

Usermanagement = get_user_model()

class EmailAuthBackend:
    def authenticate(self,request,username=None,password=None):
        print(request)
        try:
            user = Usermanagement.objects.get(emailid=username)
            print(password)
            print(user.password)
            # print(check_password(password))
            # print(user.check_password(password))
            if user.check_password(password):
                return user
            return None
            
        except user.DoesNotExist:
            return None
    
    def get_user(self,user_id): 
        try:
            return user.objects.get(pk=user_id)
        except user.DoesNotExist:
            return None

views.py

# views.py

def loginPage(request):
    # POST
    if request.method == 'POST':
        form = AuthenticationForm(request,data=request.POST)

# loginPage.html中邮箱输入框name属性为username,密码输入框name属性为password

        if form.is_valid(): # 表单验证通过
            email = request.POST['username']
            password = request.POST['password']
            # 调试输出
            print("EMAIL: ",email)
            print("PASSWORD: ",password)
            # 用户认证
            user = authenticate(request,username=email,password=password)
            print("Authenticated ",user) # 调试输出
            print(user)

            if user is not None: # 找到用户
                login(request,user,backend='accounts.backends.EmailAuthBackend')
                messages.info(request, f"你已登录,当前账号:{email}")
                return redirect("home")

            else: # 未找到用户
                messages.error(request,"用户不存在")
                return HttpResponse("用户不存在,无法登录")

        else: # 表单验证失败
            messages.error(request,"用户名或密码无效")
            return HttpResponse("表单无效")
    # GET
    else:
        form = AuthenticationForm()
        context = {"form":form}
        return render(request,"loginPage.html",context=context)

遇到的问题

  • check_password始终返回False
  • 数据库中存储的是明文密码(例如:password=admin)
  • loginPage.html中邮箱输入框name属性为username,密码输入框name属性为password

故障排查与解决方案

1. 明文密码导致验证失败

Django的check_password方法仅支持验证哈希加密后的密码字符串,数据库中存储明文必然导致验证失败。解决方式:

  • 通过Shell创建用户时,必须调用set_password()方法生成哈希密码,而非直接赋值:
    from accounts.models import Usermanagement
    user = Usermanagement(emailid='test@example.com')
    user.set_password('admin')  # 自动哈希加密
    user.save()
    
  • 遗留数据库中的现有明文密码,可编写批量更新脚本,遍历用户调用set_password()后保存。

2. 认证后端代码错误

EmailAuthBackend存在两处语法错误:

  • except user.DoesNotExist: 应改为except Usermanagement.DoesNotExist:(局部变量user无法调用DoesNotExist异常)
  • get_user方法中return user.objects.get(pk=user_id) 应改为return Usermanagement.objects.get(pk=user_id)

修正后的backends.py:

#backends.py

from django.contrib.auth import get_user_model

Usermanagement = get_user_model()

class EmailAuthBackend:
    def authenticate(self, request, username=None, password=None):
        try:
            user = Usermanagement.objects.get(emailid=username)
            if user.check_password(password):
                return user
            return None
        except Usermanagement.DoesNotExist:
            return None
    
    def get_user(self, user_id): 
        try:
            return Usermanagement.objects.get(pk=user_id)
        except Usermanagement.DoesNotExist:
            return None

3. 自定义用户模型合规性检查

确保Usermanagement模型满足Django自定义用户模型的核心要求:

  • 继承AbstractBaseUser(无需默认字段时优先选择)
  • 指定USERNAME_FIELD = 'emailid'(将邮箱作为登录标识)
  • 实现UserManager类,提供create_user和create_superuser方法

示例适配模型:

# accounts/models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models

class UserManager(BaseUserManager):
    def create_user(self, emailid, password=None):
        if not emailid:
            raise ValueError('用户必须提供邮箱')
        user = self.model(emailid=emailid)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, emailid, password):
        user = self.create_user(emailid, password)
        user.save(using=self._db)
        return user

class Usermanagement(AbstractBaseUser):
    emailid = models.EmailField(unique=True)
    # 你的其他遗留字段
    is_active = models.BooleanField(default=True)  # 建议保留,用于控制用户状态

    objects = UserManager()

    USERNAME_FIELD = 'emailid'

    def __str__(self):
        return self.emailid

4. 登录表单优化

默认AuthenticationForm验证的是username字段,与你的emailid不匹配,可自定义登录表单适配:

# accounts/forms.py
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import get_user_model

Usermanagement = get_user_model()

class EmailAuthenticationForm(AuthenticationForm):
    class Meta:
        model = Usermanagement
        fields = ('emailid', 'password')

在views.py中替换为自定义表单即可。


内容的提问来源于stack exchange,提问作者Nipun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 09:50:27