Django и DRF Почему мой пароль не хэшируется

Я использую DRF и у меня есть эти части кода как модели, представление регистра и сериализатор Но каждый раз, когда я регистрирую пользователя, пароль не хэшируется, и я не могу понять, почему.

models.py

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

        email = self.normalize_email(email).lower()

        user = self.model(email=email)
        user.set_password(password)
        user.save()

        return user


    def create_superuser(self, email, password, **extra_fields):
        if not password:
            raise ValueError("Password is required")

        user = self.create_user(email, password)
        user.is_superuser = True
        user.is_staff = True
        user.save()

        return user

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=255, unique=True)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    role = models.CharField(max_length=255)
    department = models.CharField(max_length=255)

    is_active = models.BooleanField(default=True)
    is_verified = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = UserManager()

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["first_name", "last_name", "role", "department"]

    def __str__(self):
        return self.email

serializers.py

class RegisterSerializer(serializers.ModelSerializer):
    email = serializers.CharField(max_length=255)
    password = serializers.CharField(min_length=8, write_only=True)
    first_name = serializers.CharField(max_length=255)
    last_name = serializers.CharField(max_length=255)
    role = serializers.CharField(max_length=255)
    department = serializers.CharField(max_length=255)

    class Meta:
        model = User
        fields = ["email", "password", "first_name", "last_name", "role", "department"]

    def create(self, validated_data):
        return User.objects.create(**validated_data)

    def validate_email(self, value):
        if User.objects.filter(email=value).exists():
            raise serializers.ValidationError("This email already exists!")
        return value

views.py

class RegisterView(APIView):
    serializer_class = RegisterSerializer

    def post(self, request, *args):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        user_data = serializer.data
        user = User.objects.get(email=user_data.get("email"))


        return Response(user_data, status=status.HTTP_201_CREATED)

По какой-то причине, которую я не знаю, при создании пользователя пароль сохраняется открытым текстом. Он не хэширует пароли. Однако пароль суперпользователя хэшируется, потому что я создал его с помощью командной строки, но api не хэширует пароль. Мне нужна помощь, чтобы исправить это.

enter image description here

Вместо передачи простого пароля следует использовать метод make_password, предоставляемый django.

from django.contrib.auth.hashers import make_password

make_password(password, salt=None, hasher='default')

Создает хэшированный пароль в формате, используемом данным приложением. Принимает один обязательный аргумент: пароль в виде обычного текста (строка или байт). Опционально вы можете указать соль и алгоритм хэширования, если не хотите использовать значения по умолчанию (первый элемент параметра PASSWORD_HASHERS). Имя алгоритма каждого хэшера указано в разделе Включенные хэшеры. Если аргумент password равен None, возвращается непригодный пароль (который никогда не будет принят функцией check_password()).

Вы можете попробовать что-то вроде этого

hashed_pass = make_password(your_password_here, salt=None, hasher='default')
user = self.create_user(email, hashed_pass)

Источник: https://docs.djangoproject.com/en/4.1/topics/auth/passwords/

Попробуйте это:

    def create(self, validated_data):
        password = validated_data.pop('password')
        user = User.objects.create(**validated_data)
        user.set_password(password)
        user.save()
        return user

Я нашел, почему это не работает. В методе create в RegisterSerializer я сделал return User.objects.create(**validated_data) который сохраняет данные запроса в базе данных, включая пароль, без предварительного хеширования. Правильным способом является вызов метода create_user вместо этого, например, так return User.objects.create_user(**validated_data), поскольку этот метод имеет механизм set_password для хэширования пароля.

Вернуться на верх