Django自定义用户模型中create_password字段无法哈希问题求助
如何在自定义AbstractBaseUser模型中对自定义密码字段进行哈希处理
问题核心在于Django的AbstractBaseUser类默认是基于password字段实现密码哈希逻辑的,包括set_password()和check_password()方法都是针对这个字段设计的。当你把字段名改成create_password后,默认的哈希机制就不再生效了——哪怕你调用set_password(),它依然会把哈希值存入原本的password字段(而你现在的模型里可能已经没有这个字段,或者没用到它)。
下面提供两种可行的解决方案:
方案一:重写密码处理方法适配自定义字段
如果你坚持要用create_password作为存储哈希密码的字段,需要在自定义User模型中重写set_password()和check_password()方法,让它们指向你的新字段:
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from django.db import models from django.contrib.auth.hashers import make_password, check_password class CustomUserManager(BaseUserManager): def create_user(self, email, raw_password, **extra_fields): email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(raw_password) # 调用重写后的方法 user.save(using=self._db) return user class CustomUser(AbstractBaseUser): email = models.EmailField(unique=True) create_password = models.CharField(max_length=150) # 其他自定义字段... objects = CustomUserManager() USERNAME_FIELD = 'email' def set_password(self, raw_password): # 生成密码哈希并赋值给create_password self.create_password = make_password(raw_password) self._password = raw_password # 跟踪密码修改状态,兼容Django内部逻辑 def check_password(self, raw_password): # 验证原始密码与create_password中的哈希是否匹配 return check_password(raw_password, self.create_password)
方案二:保留默认password字段,用自定义字段接收输入(推荐)
这种方式更贴合Django的原生设计,避免重写核心方法:
- 你的自定义User模型继承
AbstractBaseUser后,默认已经包含password字段(无需自己定义),只需添加create_password作为临时接收原始密码的字段:
class CustomUser(AbstractBaseUser): email = models.EmailField(unique=True) create_password = models.CharField(max_length=150, blank=True, null=True) # 其他自定义字段... objects = CustomUserManager() USERNAME_FIELD = 'email'
- 在创建/更新用户时,用
create_password的原始值调用set_password(),将哈希存入默认的password字段,之后清空明文密码:
# 创建用户示例 user = CustomUser(email='user@example.com', create_password='raw_password123') user.set_password(user.create_password) # 生成哈希存入password字段 user.create_password = None # 清空明文,避免存储 user.save()
注意事项
- 不要直接给
create_password赋值明文密码后保存,必须通过set_password()方法处理哈希。 - 如果你之前覆盖了
AbstractBaseUser的password字段,建议删除自定义的password定义,直接使用父类自带的字段,避免冲突。
内容的提问来源于stack exchange,提问作者harshit
相关产品推荐
相关产品推荐

