Enforcing password strength requirements with django.contrib.auth.views.password_change

后端 未结 5 757
没有蜡笔的小新
没有蜡笔的小新 2020-12-22 23:31

We have a Django application that requires a specific level of password complexity. We currently enforce this via client-side JavaScript which can easily be defeated by some

相关标签:
5条回答
  • 2020-12-23 00:10

    Django 1.9 offers a built-in password validation to help prevent the usage of weak passwords by users. It's enabled by modifing the AUTH_PASSWORD_VALIDATORS setting in our project. By default Django comes with following validators:

    • UserAttributeSimilarityValidator, which checks the similarity between the password and a set of attributes of the user.
    • MinimumLengthValidator, which simply checks whether the password meets a minimum length. This validator is configured with a custom option: it now requires the minimum length to be nine characters, instead of the default eight.
    • CommonPasswordValidator, which checks whether the password occurs in a list of common passwords. By default, it compares to an included list of 1000 common passwords.
    • NumericPasswordValidator, which checks whether the password isn’t entirely numeric.

    This example enables all four included validators:

    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',
        },
    ]
    
    0 讨论(0)
  • 2020-12-23 00:12

    I think you should just write your own validator ( or use RegexValidator, see: http://docs.djangoproject.com/en/dev/ref/validators/ ) if you use forms or write some other script checking for regular expressions. This should be a simple task. Also I don't think there is any builtin mechanism, simply because each person understands the concept of "strong password" a little bit different.

    0 讨论(0)
  • 2020-12-23 00:14

    I also went with a custom form for this. In urls.py specify your custom form:

    (r'^change_password/$', 'django.contrib.auth.views.password_change',
         {'password_change_form': ValidatingPasswordChangeForm}),
    

    Inherit from PasswordChangeForm and implement validation:

    from django import forms
    from django.contrib import auth
    
    class ValidatingPasswordChangeForm(auth.forms.PasswordChangeForm):
        MIN_LENGTH = 8
    
        def clean_new_password1(self):
            password1 = self.cleaned_data.get('new_password1')
    
            # At least MIN_LENGTH long
            if len(password1) < self.MIN_LENGTH:
                raise forms.ValidationError("The new password must be at least %d characters long." % self.MIN_LENGTH)
    
            # At least one letter and one non-letter
            first_isalpha = password1[0].isalpha()
            if all(c.isalpha() == first_isalpha for c in password1):
                raise forms.ValidationError("The new password must contain at least one letter and at least one digit or" \
                                            " punctuation character.")
    
            # ... any other validation you want ...
    
            return password1
    
    0 讨论(0)
  • 2020-12-23 00:20

    I'd just install django-passwords and let that handle it for you: https://github.com/dstufft/django-passwords

    After that you can simply subclass the registration form and replace the field with a PasswordField.

    0 讨论(0)
  • 2020-12-23 00:29

    As some eluded to with the custom validators, here's the approach I would take...

    Create a validator:

    from django.core.exceptions import ValidationError
    from django.utils.translation import ugettext as _
    
    def validate_password_strength(value):
        """Validates that a password is as least 7 characters long and has at least
        1 digit and 1 letter.
        """
        min_length = 7
    
        if len(value) < min_length:
            raise ValidationError(_('Password must be at least {0} characters '
                                    'long.').format(min_length))
    
        # check for digit
        if not any(char.isdigit() for char in value):
            raise ValidationError(_('Password must contain at least 1 digit.'))
    
        # check for letter
        if not any(char.isalpha() for char in value):
            raise ValidationError(_('Password must contain at least 1 letter.'))
    

    Then add the validator to the form field you're looking to validate:

    from django.contrib.auth.forms import SetPasswordForm
    
    class MySetPasswordForm(SetPasswordForm):
    
        def __init__(self, *args, **kwargs):
            super(MySetPasswordForm, self).__init__(*args, **kwargs)
            self.fields['new_password1'].validators.append(validate_password_strength)
    
    0 讨论(0)
提交回复
热议问题