简体   繁体   中英

Django and DRF Why isn't my password hashing

I am using DRF and I have these pieces of code as models, register view and serializer But anytime I signup a user the password does not hashed and I can't see to figure out why.

models.py

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

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

        user = self.model(email=email, **kwargs)
        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)

for some reason, which I don't know anytime a user is created the password is save in clear text. It does not hash the passwords. The superuser's password is however hashed because I created it with the command line but the api doesn't hash the password. I some help to fix this.

在此处输入图像描述

Instead of passing plain password you should use make_password method provided by django.

from django.contrib.auth.hashers import make_password

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

Creates a hashed password in the format used by this application. It takes one mandatory argument: the password in plain-text (string or bytes). Optionally, you can provide a salt and a hashing algorithm to use, if you don't want to use the defaults (first entry of PASSWORD_HASHERS setting). See Included hashers for the algorithm name of each hasher. If the password argument is None, an unusable password is returned (one that will never be accepted by check_password()).

You can try something like this

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

Source: https://docs.djangoproject.com/en/4.1/topics/auth/passwords/

Try this:

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

I found why it wasn't working. In the create method in the RegisterSerializer I did a return User.objects.create(**validated_data) which saves on the request data in the database, including the password without hashing it first. The correct way is to be calling the create_user method instead, like so return User.objects.create_user(**validated_data) since that method has the set_password mechanism to hash the password.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM