Django自定义Employee模型密码未哈希存入PostgreSQL问题排查
Django自定义用户模型密码未哈希排查与解决
可能的原因
- 自定义
EmployeeManager的create_employee方法直接将明文密码赋值给password字段,未调用Django提供的哈希方法(set_password/make_password),或调用逻辑存在错误 - 自定义
Employee模型错误覆盖了password字段,比如用TextField替代了AbstractBaseUser默认的CharField(max_length=128),破坏了父类的密码处理逻辑 - 哈希操作在实例保存之后执行,导致明文密码先被存入数据库
PASSWORD_HASHERS配置存在拼写错误、顺序不合理,或修改后未重启服务导致配置未生效
解决方案
1. 修正自定义Manager的创建方法
确保create_employee方法中正确处理密码哈希,示例代码:
from django.contrib.auth.base_user import BaseUserManager from django.contrib.auth.hashers import make_password class EmployeeManager(BaseUserManager): def create_employee(self, email, password=None, **extra_fields): if not email: raise ValueError('必须填写邮箱字段') email = self.normalize_email(email) employee = self.model(email=email, **extra_fields) # 二选一:用set_password自动处理哈希,或用make_password生成哈希值后赋值 employee.set_password(password) # 或者 employee.password = make_password(password) employee.save(using=self._db) return employee
禁止直接写
employee.password = password,这会直接存储明文
2. 检查自定义用户模型的字段定义
确保Employee模型正确继承AbstractBaseUser,不要手动覆盖password字段:
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.db import models class Employee(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True) # 自定义业务字段,比如姓名、部门等 name = models.CharField(max_length=50) department = models.CharField(max_length=100) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) objects = EmployeeManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['name'] # 无需重新定义password字段,AbstractBaseUser已包含正确的密码字段逻辑
如果之前手动定义过password字段,直接删除即可。
3. 验证保存逻辑与配置
- 创建用户后打印
employee.password,正常情况下应该输出以pbkdf2_sha256$/argon2$等开头的哈希字符串,而非明文 - 检查
settings.py中的PASSWORD_HASHERS配置,确保默认哈希器排在最前面:
PASSWORD_HASHERS = [ 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.Argon2PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', ]
- 执行迁移后重启Django服务,确保配置生效
4. 测试创建流程
用以下代码快速验证密码哈希效果:
employee = Employee.objects.create_employee(email='test@example.com', password='plain123456', name='测试用户') print(employee.password) # 输出哈希字符串则说明处理正常
内容的提问来源于stack exchange,提问作者Vamsee.
相关产品推荐
相关产品推荐

