Django:如何应用内置的密码验证器?

Django: How to apply the built-in password validators?

我喜欢在注册表单上测试 django 内置验证器。所以我添加了这个...


settings.py

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 9,
        }
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

forms.py

from django.contrib.auth.models import User
from django import forms
import django.contrib.auth.password_validation as validators


class UserRegistrationForm(forms.ModelForm):
    password = forms.CharField(label='Password',
                               widget=forms.PasswordInput)
    password2 = forms.CharField(label='Repeat password',
                                widget=forms.PasswordInput)

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


    # --- check duplicate
    def clean_password2(self):
        cd = self.cleaned_data
        if cd['password'] != cd['password2']:
            raise forms.ValidationError('Passwords don\'t match.')
        return cd['password2']

    # --- django built-in validator
    def pass_validate(self):
        password = self.cleaned_data('password')
        try:
            validators(password, self.instance)
        except forms.ValidationError as error:
            self.add_error('password', error)
        return password

views.py

<...>
def register(request):
    if request.method == 'POST':
        user_form = UserRegistrationForm(request.POST)
        if user_form.is_valid():
            # Create a new user object but avoid saving it yet
            new_user = user_form.save(commit=False)
            # Set the chosen password
            new_user.set_password(
                user_form.cleaned_data['password'])
            # Save the User object
            new_user.save()
            return render(request,
                          'account/register_done.html',
                          {'new_user': new_user})
    else:
        user_form = UserRegistrationForm()
    return render(request,
                  'account/register.html',
                  {'user_form': user_form})
<...>

所以我的问题是 “如何以正确的方式应用内置密码验证器”?我需要一个特殊的 validators.py 吗?但我猜我把 forms.py 中的函数弄错了。

您可以实施 UserCreationForm 以便您的 AUTH_PASSWORD_VALIDATORS 可以正常工作。

例如:

forms.py

from django.contrib.auth.forms import UserCreationForm

class RegisterForm(UserCreationForm):

    def clean_email(self):
        email = self.cleaned_data['email']
        if User.objects.filter(email=email).exists():
            raise ValidationError('Email Already Exists')

        return email

    class Meta:
        model = User
        fields = ['username', "email", "password1", "password2"]

views.py

def register(request):
    if request.method == "POST":
        form = RegisterForm(request.POST or None)
        if form.is_valid():
           form.save()
           return redirect('some_view')
    else:
        form = RegisterForm()
    return render(request, 'template', {'form': form})

与其他模型验证一样,需要显式调用密码验证。您可以通过直接调用 validate_password 来触发密码验证。

from django.contrib.auth.models import User
from django import forms
from django.contrib.auth.password_validation import validate_password


class UserRegistrationForm(forms.ModelForm):
    password = forms.CharField(label='Password',
                               widget=forms.PasswordInput)
    password2 = forms.CharField(label='Repeat password',
                                widget=forms.PasswordInput)

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

    # --- django built-in validator
    def clean_password(self):
        password = self.cleaned_data['password']
        validate_password(password)
        return password

    # --- check duplicate
    def clean_password2(self):
        cd = self.cleaned_data
        if cd['password'] != cd['password2']:
            raise forms.ValidationError('Passwords don\'t match.')
        return cd['password2']

如果您不想使用所有默认值,您可以通过 validate_password 个单独的验证器。参见 help(validate_password)