繁体   English   中英

Django-Rest-Framework 自定义用户没有散列密码(序列化程序问题)

[英]Django-Rest-Framework Custom User not Hashing Password (Serializer Issue)

我正在尝试使用令牌身份验证,但由于我的创建用户序列化程序没有对密码进行哈希处理,它无法正常工作。 我可以使用超级用户登录,因为它有一个散列密码。 使用 rest_auth 和 rest_framework.authtoken。 user.set_password 命令应该对密码进行哈希处理,那么之前的代码有问题吗?

class CreateUserSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.CharField()
    password = serializers.CharField(write_only = True, style = {'input_type': 'password'})

    class Meta:
        model = get_user_model()
        fields = (
            'id','username', 'password', 
            'email', 'first_name', 'last_name'
        )
        write_only_fields = ('password')
        read_only_fields = ('is_staff', 'is_superuser', 'is_active')

        def create(self, validated_data):
            password = validated_data.pop('password')
            user = super().create(validated_data)
            user.set_password(validated_data['password'])
            user.save()
            return user
class CreateUserAPIView(CreateAPIView):
    """
    Create a new user.
    """
    serializer_class = CreateUserSerializer
    permission_classes = [AllowAny]

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data = request.data)
        serializer.is_valid(raise_exception = True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)

        # Create a token that will be used for future auth
        token = Token.objects.create(user = serializer.instance)
        token_data = {"token": token.key}

        return Response(
            {**serializer.data, **token_data},
            status = status.HTTP_201_CREATED,
            headers = headers
        )
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 20,

    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),

    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = (
            'url', 'username', 'email', 'groups', 'workflow_step',
            'first_name', 'last_name', 
            'birthdate',
            'address_street1', 'address_street2', 'address_city', 
            'address_state', 'address_postal_code', 'address_country', 'phone'
        )
class User(AbstractUser):
    # Application process
    workflow_step = models.CharField(max_length=100, default='', blank=True)

    is_verified = models.BooleanField(default=False)

    # Basic information
    # first_name (in django.contrib.auth.models.User)
    # last_name (in django.contrib.auth.models.User)
    # email (in django.contrib.auth.models.User)

    # Advanced Information
    birthdate = models.DateField(blank=True, null=True)
    address_street1 = models.CharField(max_length=100, blank=True)
    address_street2 = models.CharField(max_length=100, default='', blank=True)
    address_city = models.CharField(max_length=100, blank=True)
    address_state = models.CharField(max_length=50, blank=True)
    address_postal_code = models.CharField(max_length=30, blank=True)
    address_country = models.CharField(max_length=100, blank=True)
    phone = models.CharField(max_length=30, blank=True)

这可能为时已晚,但对于任何有此问题的人来说。 您需要将create函数直接放在序列化程序类中,在您的情况下,您将它放在Meta子类中

您需要做的第二件事是使用

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

祝你好运

CreateUserSerializer.create你这样做:

        password = validated_data.pop('password')
        ...
        user.set_password(validated_data['password'])

当您调用set_password时, password密钥已从validated_data中删除。 您可能希望将set_password行改为:

        user.set_password(password)

您可以使用make_passowrd函数按散列顺序:

class CreateUserSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.CharField()
    password = serializers.CharField(write_only = True, style = {'input_type': 'password'})

    class Meta:
        model = get_user_model()
        fields = (
            'id','username', 'password', 
            'email', 'first_name', 'last_name'
        )
        write_only_fields = ('password')
        read_only_fields = ('is_staff', 'is_superuser', 'is_active')

        def create(self, validated_data):
            password = validated_data.pop('password')
            user = super().create(validated_data)
            user.set_password( make_password(validated_data['password']))
            user.save()
            return user

在此处阅读有关密码管理的所有信息

您在散列之前删除了“密码”键。 您需要将user.set_password(validated_data['password'])更改为user.set_password(password)从验证数据中弹出并存储到密码变量。

这对我有用..试试这个

class UserSerializer(serializers.ModelSerializer):
    # <Your other UserSerializer stuff here>

    def create(self, validated_data):
        password = validated_data.pop('password', None)
        instance = self.Meta.model(**validated_data)
        if password is not None:
            instance.set_password(password)
        instance.save()
        return instance

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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