Django по-разному хэширует мои пароли при создании пользователя и при попытке аутентификации пользователя

У меня проблемы с аутентификацией, и я обнаружил, что проблема в том, что когда я создаю пользователя, его пароль хэшируется не в PBKDF2, а в другом стиле. Вместо этого пароли всегда имеют такой формат: !iak7ijJTzsXRgsbwqtQBtXCZeU3Ccd96k2PpOCRa .

Однако, когда я работаю в моих представлениях make_password и check_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 - это означает, что для пользователя был установлен непригодный пароль - остальное значение является случайной строкой, которая никогда не будет успешно проверена.

Итак, вопрос в том, почему задается непригодный пароль? Из вашего кода я вижу две возможности:

  1. UserManager.create_super_user вообще не устанавливает пароль пользователя - если вы используете это для создания пользователей, то пароль для них не будет установлен.

  2. Если вы используете CreateUserSerializer, то может оказаться, что значение password равно None - нам нужно посмотреть определение сериализатора, чтобы подтвердить, будет ли нулевое значение считаться допустимым. Я думаю, что это наиболее вероятная проблема. Передача 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')
Вернуться на верх