Django 在创建用户时对我的密码进行哈希处理与尝试对用户进行身份验证时不同

Django is hashing my passwords different when creating a User vs trying to authenticate a user

我在进行身份验证时遇到问题,我发现问题出在我创建用户时,他们的密码散列方式与 PBKDF2 不同。相反,密码始终采用如下格式:!iak7ijJTzsXRgsbwqtQBtXCZeU3Ccd96k2PpOCRa .

但是,当我在我的视图中工作时,make_passwordcheck_password 正在使用 PBKDF2。

型号:

class UserManager(BaseUserManager):
    def create_user(self, email, password):
        if not email:
            raise ValueError("User must have an email address")

        user = self.model(
            email = self.normalize_email(email),
        )

        user.set_password(password)
        user.save()
        return user

    def create_super_user(self, email, password=None):
        if not email:
            raise ValueError("User must have an email address")

        user = self.model(
            email = self.normalize_email(email),
        )

        user.is_admin = True
        user.save()
        return user

class User(AbstractBaseUser):
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    
    email=models.EmailField(
        verbose_name='Email',
        max_length=255,
        unique=True
    )

    password=models.CharField(
        max_length=255, 
        verbose_name='password'
    )

    username = None
    first_name = None
    last_name = None

    is_active = models.BooleanField(default=True)

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()
    
    def __str__(self):
        return self.email

我怀疑问题出在我的自定义模型上,但它与我为另一个没有问题的应用程序编写的模型相同。

注册查看:

class CreateUser(APIView):
    serializer_class = CreateUserSerializer
    def post(self, request, format='json'):
        serializer = self.serializer_class(data=request.data)

        if serializer.is_valid():
            email = serializer.data.get('email')
            password = serializer.data.get('password')

            userObj = User.objects.create_user(email=email, password=password)
            userObj.save()
            return Response(status=status.HTTP_201_CREATED)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

登录视图:

class LogIn(APIView):
    serializer_class = LogInSerializer
    authentication_classes = [SessionAuthentication, BasicAuthentication]

    def post(self, request, format='json'):
        serializer = self.serializer_class(data=request.data)

        if serializer.is_valid():
            email = serializer.data.get('email')
            password = serializer.data.get('password')

            tObj = User.objects.get(email=email)
            hashed_pwd = make_password("123456")
            print(hashed_pwd)
            print(tObj.password)

            print(tObj.check_password(password))
            

            user = authenticate(email=email, password=password)
            print(user)

            if user is not None:

密码值开头的!在Django中有特殊含义——表示已经为用户设置了一个unusable password——其余的值只是一个随机值永远不会成功验证的字符串。

所以问题是为什么设置了一个不可用的密码?我可以从您的代码中看到两种可能性:

  1. UserManager.create_super_user 根本不设置用户密码 - 如果您使用它来创建用户,则不会为他们设置密码。

  2. 如果您使用的是 CreateUserSerializer,那么 password 的值可能是 None - 我们需要查看序列化器定义确认 null 值是否被视为有效。我认为这是最有可能的问题。将 None 传递给 create_user 将导致 set_password 设置无法使用的密码。然后,您需要调查为什么将空值传递给序列化程序。

问题出在 solarissmoke 使用 CreateUserSerializer 提出的问题。我将我的密码设置为只写,这不允许我查看密码,而是返回 None.

我改变了我的看法:

class CreateUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('email', 'password')
        extra_kwargs = {
            'password' : {'write_only': True}
        }

致此(修正版):

class CreateUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('email', 'password')