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

Django自定义用户模型密码未哈希,非超级用户无法登录求助

问题分析与解决方案

核心问题

  1. ModelForm直接保存明文密码:你的StudentRegistrationForm和TeacherRegistrationForm继承自ModelForm,直接调用form.save()时,会把表单中的明文password直接存入数据库,没有调用set_password()进行哈希处理。
  2. 代理模型的create_user未被触发:ModelForm默认使用模型的objects.create()方法创建实例,不会调用你自定义管理器中的create_user(该方法包含密码哈希逻辑)。
  3. Admin后台未适配自定义用户模型:默认的Django Admin不会自动处理自定义用户模型的密码哈希,也无法正确创建普通用户。
  4. 权限方法限制过严:has_perm方法直接返回self.is_admin,导致普通用户(非admin)没有任何权限,间接影响登录后的操作,核心登录失败原因还是密码未哈希。

解决方案

1. 修改表单,手动处理密码哈希

修改forms.py,重写save()方法,显式调用用户模型的set_password():

from django import forms
from .models import Student, Teacher

class StudentRegistrationForm(forms.ModelForm):
    # 显式定义密码字段,使用密码输入组件
    password = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = Student
        fields = ['email', 'password']

    def save(self, commit=True):
        user = super().save(commit=False)
        # 对密码进行哈希处理
        user.set_password(self.cleaned_data["password"])
        if commit:
            user.save()
        return user

class TeacherRegistrationForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = Teacher
        fields = ['email', 'password']

    def save(self, commit=True):
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password"])
        if commit:
            user.save()
        return user

2. 修复自定义用户模型的权限方法

has_perm方法当前只允许admin用户拥有权限,修改为更合理的逻辑:

# 在UserAccount模型中修改
def has_perm(self, perm, obj=None):
    # 普通用户默认拥有基本权限,可根据业务需求调整
    return self.is_active

def has_module_perms(self, app_label):
    return self.is_active

3. 适配Django Admin后台

创建admin.py,自定义UserAdmin来处理密码哈希和用户创建:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import UserAccount, Student, Teacher

class CustomUserAdmin(UserAdmin):
    # 自定义列表显示字段
    list_display = ('email', 'type', 'is_active', 'is_staff')
    # 自定义编辑页面字段分组
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('权限设置', {'fields': ('is_active', 'is_staff', 'is_superuser', 'is_student', 'is_teacher')}),
        ('用户类型', {'fields': ('type',)}),
    )
    # 自定义添加用户页面字段
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2', 'type', 'is_active', 'is_staff'),
        }),
    )
    ordering = ('email',)
    filter_horizontal = ()

# 注册模型与自定义Admin
admin.site.register(UserAccount, CustomUserAdmin)
admin.site.register(Student)
admin.site.register(Teacher)

4. 验证代理模型保存逻辑

当前代理模型的save方法已正确设置用户类型,无需修改:

  • Student模型自动设置type = STUDENT和is_student = True
  • Teacher模型自动设置type = TEACHER和is_teacher = True

测试步骤

  1. 删除数据库中已存在的明文密码用户记录
  2. 执行迁移:python manage.py migrate
  3. 通过表单注册学生/教师,检查数据库中password字段是否为哈希值(以pbkdf2_sha256$开头)
  4. 使用注册用户登录,确认登录功能正常
  5. 在Admin后台创建用户,使用密码双输入框,确认密码被正确哈希

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:43:20