将 django 密码验证器与 django rest 框架 validate_password 集成 [英] integrate django password validators with django rest framework validate_password

查看:25
本文介绍了将 django 密码验证器与 django rest 框架 validate_password 集成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试集成 django 验证器 1.9 带有 django rest 框架序列化程序.但是序列化的用户"(来自 django rest 框架)与 django 验证器不兼容.

I'm trying to integrate django validators 1.9 with django rest framework serializers. But the serialized 'user' (of django rest framework) is not compatible with the django validators.

这是serializers.py

Here is the serializers.py

import django.contrib.auth.password_validation as validators
from rest_framework import serializers

    class RegisterUserSerializer(serializers.ModelSerializer):

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

        class Meta:
            model = User
            fields = ('id', 'username', 'email, 'password')

        def validate_password(self, data):
            validators.validate_password(password=data, user=User)
            return data

        def create(self, validated_data):
            user = User.objects.create_user(**validated_data)
            user.is_active = False
            user.save()
            return user

我设法让 MinimumLengthValidator 和 NumericPasswordValidator 正确,因为这两个函数验证都不使用用户"进行验证.源代码在这里

I managed to get MinimumLengthValidator and NumericPasswordValidator correct because both function validate don't use 'user' in validating. Source code is here

摘自django源代码:

Excerpt from django source code:

def validate(self, password, user=None):
        if password.isdigit():
            raise ValidationError(
                _("This password is entirely numeric."),
                code='password_entirely_numeric',
            )

对于像 UserAttributeSimilarityValidator 这样的其他验证器,该函数在验证中使用另一个参数 'user'('user' 是 django 用户模型,如果我没记错的话)

For other validators like UserAttributeSimilarityValidator, the function uses another one argument 'user' in validating ('user' is django User model, if I'm not wrong)

摘自django源代码:

Excerpt from django source code:

 def validate(self, password, user=None):
        if not user:
            return

        for attribute_name in self.user_attributes:
            value = getattr(user, attribute_name, None)

如何将序列化的 User 更改为 django 验证器(UserAttributeSimilarityValidator)可以看到的内容

摘自django源代码:

Excerpt from django source code:

def validate(self, password, user=None):
        if not user:
            return

        for attribute_name in self.user_attributes:
            value = getattr(user, attribute_name, None)
            if not value or not isinstance(value, string_types):
                continue

<小时>

编辑

Django Rest Framework 可以获得 Django 的所有内置密码验证(但它就像一个黑客).这里有一个问题:

Django Rest Framework can get all of Django's built-in password validation (but it's like a hack). Here's a problem:

validationError 是这样的

The validationError is like this

[ValidationError(['这个密码太短.它必须包含在至少 8 个字符.']), ValidationError(['这个密码完全是数字.'])]

[ValidationError(['This password is too short. It must contain at least 8 characters.']), ValidationError(['This password is entirely numeric.'])]

验证不包含字段.Django rest 框架将其视为

The validation doesn't contain a field. Django rest framework see it as

{
    "non_field_errors": [
        "This password is too short. It must contain at least 8 characters.",
        "This password is entirely numeric."
    ]
}

如何在 raise ValidationError

推荐答案

就像你提到的,当你使用 UserAttributeSimilarityValidator 验证 validate_password 方法中的 password 时code> 验证器,您没有 user 对象.

Like you mentioned, when you validate the password in validate_password method using UserAttributeSimilarityValidator validator, you don't have the user object.

我建议您不要执行字段级验证,而是执行 对象级验证 通过在序列化器上实现 validate 方法:

What I suggest that instead of doing field-level validation, you shall perform object-level validation by implementing validate method on the serializer:

import sys
from django.core import exceptions
import django.contrib.auth.password_validation as validators

class RegisterUserSerializer(serializers.ModelSerializer):

     # rest of the code

     def validate(self, data):
         # here data has all the fields which have validated values
         # so we can create a User instance out of it
         user = User(**data)

         # get the password from the data
         password = data.get('password')

         errors = dict() 
         try:
             # validate the password and catch the exception
             validators.validate_password(password=password, user=User)

         # the exception raised here is different than serializers.ValidationError
         except exceptions.ValidationError as e:
             errors['password'] = list(e.messages)

         if errors:
             raise serializers.ValidationError(errors)

         return super(RegisterUserSerializer, self).validate(data)

这篇关于将 django 密码验证器与 django rest 框架 validate_password 集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆