[英]Django-Rest-Framework Custom User not Hashing Password (Serializer Issue)
I am trying to use token authentication, but it is not working due to my create user serializer not hashing the passwords.我正在尝试使用令牌身份验证,但由于我的创建用户序列化程序没有对密码进行哈希处理,它无法正常工作。 I am able to login with the superuser as that has a hashed password.
我可以使用超级用户登录,因为它有一个散列密码。 Using rest_auth and rest_framework.authtoken.
使用 rest_auth 和 rest_framework.authtoken。 The user.set_password command is supposed to hash the password, so is there an issue with the prior code?
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)
This is probably too late, but for anyone who has this issue.这可能为时已晚,但对于任何有此问题的人来说。 you need to put the
create
function directly inside the serializer class, in your case you have it in the Meta
subclass您需要将
create
函数直接放在序列化程序类中,在您的情况下,您将它放在Meta
子类中
The second thing you need to do is to use您需要做的第二件事是使用
def create(self, validated_data):
password = validated_data.pop('password')
user = super().create(validated_data)
user.set_password(password)
user.save()
return user
best of luck祝你好运
In CreateUserSerializer.create
you're doing this:在
CreateUserSerializer.create
你这样做:
password = validated_data.pop('password')
...
user.set_password(validated_data['password'])
By the time you call set_password
the password
key has been removed from validated_data
.当您调用
set_password
时, password
密钥已从validated_data
中删除。 You probably want to change the set_password
line to this instead:您可能希望将
set_password
行改为:
user.set_password(password)
You can use the make_passowrd
function in order of hashing it:您可以使用
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
You are removing the 'password' key before hashing it.您在散列之前删除了“密码”键。 You need to change
user.set_password(validated_data['password'])
this to user.set_password(password)
as you popped that from validated data and stored to password variable.您需要将
user.set_password(validated_data['password'])
更改为user.set_password(password)
从验证数据中弹出并存储到密码变量。
This works for me..try this这对我有用..试试这个
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.