如何在 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.hashersmake_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 用户密码?

如何仅使用 django 作为后端并使用 django-rest-framework 发布

如何在 React 中显示来自 django-rest-framework 的错误消息