如何在 Django Rest Framework 中散列 Django 用户密码?
Posted
技术标签:
【中文标题】如何在 Django Rest Framework 中散列 Django 用户密码?【英文标题】:How to Hash Django user password in Django Rest Framework? 【发布时间】:2017-05-10 23:51:41 【问题描述】:我正在尝试使用 Django Rest Framework 为我的用户注册创建一个 API。我按照api-guide中的步骤创建了一个序列化程序
class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'username', 'password')
extra_kwargs = 'password': 'write_only': True
def create(self, validated_data):
user = User(
email=validated_data['email'],
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
但是,我不断收到新创建的用户的Invalid password format or unknown hashing algorithm.
。我尝试使用来自django.contrib.auth.hashers
的make_password
,但我仍然无法解决此问题。
谢谢
【问题讨论】:
这可能对***.com/questions/27586095/…有帮助 【参考方案1】:你可以这样试试
from django.contrib.auth.hashers import make_password
user = User.objects.create(
email=validated_data['email'],
username=validated_data['username'],
password = make_password(validated_data['password'])
)
【讨论】:
对于任何花费太多来寻找为什么user.set_password(password)
的答案的人,当我们在用户创建期间设置密码时,这个解决方案最终会起作用。在我看来,当我尝试首先通过bulk_create
创建用户并稍后设置密码时,我遇到了竞争条件问题。【参考方案2】:
您可以覆盖 CreateAPIView 中的 perform_create 方法
from rest_framework.generics import CreateAPIView
class SignUpView(CreateAPIView):
serializer_class = SignUpSerializers
def perform_create(self, serializer):
instance = serializer.save()
instance.set_password(instance.password)
instance.save()
【讨论】:
这将保存实例两次 是的,这不是最好的方法【参考方案3】:您还可以通过将validate_password
方法添加到您的序列化程序并使其返回哈希值,将field validation function 用于password
字段。
from rest_framework.serializers import ModelSerializer
from django.contrib.auth.hashers import make_password
class UserSerializer(ModelSerializer):
class Meta:
model = backend.models.User
fields = ('username', 'email', 'password',)
validate_password = make_password
【讨论】:
【参考方案4】:您可以在视图 perform_create 方法中执行此操作:
from django.contrib.auth.hashers import make_password
def perform_create(self, instance):
current_user = self.request.user
user_exists = CustomUser.objects.filter(
email=self.request.data['email']).first()
if user_exists:
raise MethodNotAllowed
else:
instance.save(is_active=False, is_confirmed=False,
password=make_password(self.request.data['password']))
【讨论】:
【参考方案5】:在序列化器中重新定义函数create:
from django.contrib.auth.hashers import make_password
class UserSerializer(ModelSerializer):
def create(self, validated_data):
validated_data['password'] = make_password(validated_data['password'])
return super(UserSerializer, self).create(validated_data)
这一切! :D
【讨论】:
【参考方案6】:另一个简单的解决方案是在您的 create 方法中使用 User.objects.create_user(),如下所示
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
return user
【讨论】:
【参考方案7】:我知道这是一个旧线程,但我今天收到了这个问题,我想在这里分享我的解决方案。
您可以简单地定义您的序列化程序,如下所示:
class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'username', 'password')
extra_kwargs = 'password': 'write_only': True
另一方面,在您看来,您可以重写 perform_create 方法,如下所示:
class UserView(ViewSets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserCreateSerializer
def perform_create(self , serializer):
new_user =
User.objects.create(username=self.request.data.get("username"))
new_user.set_password(self.request.data.get("password"))
serializer.save(password=user.password)
这样,您可以将额外的信息传递给序列化程序进行保存。
【讨论】:
以上是关于如何在 Django Rest Framework 中散列 Django 用户密码?的主要内容,如果未能解决你的问题,请参考以下文章
Django.rest_framework:如何序列化一对多?
如何使用 TemplateHTMLRenderer 在 Django-REST-Framework 中创建/放置?
django-rest-framework:如何序列化已经包含 JSON 的字段?
如何在 Django Rest Framework 中散列 Django 用户密码?