【问题标题】:How to Hash Django user password in Django Rest Framework?如何在 Django Rest Framework 中散列 Django 用户密码?
【发布时间】: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,但我仍然无法解决此问题。

谢谢

【问题讨论】:

标签: python django authentication passwords django-rest-framework


【解决方案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)
          

          这样,您可以将额外的信息传递给序列化程序进行保存。

          【讨论】:

            猜你喜欢
            • 2016-12-15
            • 2021-02-19
            • 1970-01-01
            • 2023-03-10
            • 1970-01-01
            • 2017-02-26
            • 2019-10-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多