web-dev-qa-db-fra.com

Application des exigences de résistance des mots de passe avec Django.contrib.auth.views.password_change

Nous avons une application Django qui nécessite un niveau spécifique de complexité de mot de passe. Nous appliquons actuellement cela via JavaScript côté client qui peut facilement être vaincu par quelqu'un qui est correctement motivé.

Je n'arrive pas à trouver d'informations spécifiques sur la configuration de la validation de la force des mots de passe côté serveur à l'aide des vues intégrées de la contribution Django. Avant de réinventer la roue, existe-t-il un moyen approprié de gérer cette exigence?

46
jslatts

Je suis également allé avec un formulaire personnalisé pour cela. Dans urls.py spécifiez votre formulaire personnalisé:

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

Héritez de PasswordChangeForm et implémentez la 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
40
EMP

Django 1.9 offre une validation de mot de passe intégrée pour aider à empêcher l'utilisation de mots de passe faibles par les utilisateurs. Il est activé en modifiant le AUTH_PASSWORD_VALIDATORS mise en place de notre projet. Par défaut Django est livré avec les valideurs suivants:

  • UserAttributeSimilarityValidator, qui vérifie la similitude entre le mot de passe et un ensemble d'attributs de l'utilisateur.
  • MinimumLengthValidator, qui vérifie simplement si le mot de passe correspond à une longueur minimale. Ce validateur est configuré avec une option personnalisée: il requiert désormais une longueur minimale de neuf caractères, au lieu des huit par défaut.
  • CommonPasswordValidator, qui vérifie si le mot de passe apparaît dans une liste de mots de passe courants. Par défaut, il se compare à une liste incluse de 1000 mots de passe courants.
  • NumericPasswordValidator, qui vérifie si le mot de passe n'est pas entièrement numérique.

Cet exemple active les quatre validateurs inclus:

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',
    },
]
27
Cesar Canassa

Comme certains l'ont évité avec les validateurs personnalisés, voici l'approche que je prendrais ...

Créez un validateur:

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.'))

Ajoutez ensuite le validateur au champ du formulaire que vous souhaitez valider:

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)
14
Troy Grosfield

Je voudrais simplement installer les mots de passe Django et laisser cela le gérer pour vous: https://github.com/dstufft/Django-passwords

Après cela, vous pouvez simplement sous-classer le formulaire d'inscription et remplacer le champ par un PasswordField.

10
Alper

Je pense que vous devriez simplement écrire votre propre validateur (ou utiliser RegexValidator, voir: http://docs.djangoproject.com/en/dev/ref/validators/ ) si vous utilisez des formulaires ou écrivez d'autres script vérifiant les expressions régulières. Cela devrait être une tâche simple. De plus, je ne pense pas qu'il existe de mécanisme intégré, simplement parce que chaque personne comprend le concept de "mot de passe fort" un peu différent.

2
freakish