我正在尝试创建一个注册端点。 当我创建新用户时,密码字段中将保存纯文本。但是,当我通过管理员添加用户时,它将被散列。我不确定我在这里缺少什么。
模型.py
class UserManager(BaseUserManager):
def _create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('The given email must be set')
user = self.model(
email=self.normalize_email(email),
**extra_fields,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_admin', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
序列化器.py
from rest_framework import serializers
from django.contrib.auth import authenticate
from .models import User
class RegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User.objects.create_user(
validated_data['email'],
validated_data['password']
)
return user
查看.py
class RegisterAPI(generics.GenericAPIView):
serializer_class = RegisterSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
})
最佳答案
问题出在 RegisterSerializer.create
方法中:
def create(self, data):
user = User.objects.create(**data)
return user
您将用户的密码
作为文本,并调用User.objects.create
来创建User
实例。 UserManager
的 create
方法(最终委托(delegate)给 QuerySet
)是通用的,这意味着 password
字段将是按原样填充为输入数据,没有任何散列加盐。
由于保存为明文,Django无法确定保存的格式(典型格式为hash_algo$iterations$salt$hash
),因此无法查出散列算法,盐,从中散列;因此会出现错误无效的密码格式或未知的哈希算法。
UserManager
公开了 create_user
方法,用于通过传递纯文本密码创建用户并在那里执行所有这些操作,您应该利用该方法:
def create(self, data):
user = User.objects.create_user(**data)
# ^^^^ Here
return user
或者您可以直接在序列化程序中的用户实例上使用set_password
,但由于您可以轻松使用create_user
,因此您应该这样做。
关于python - UserManager 中的 Django set_password() 方法正在保存纯文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58838108/