2011-03-07 26 views
41

Tenemos una aplicación Django que requiere un nivel específico de complejidad de contraseñas. Actualmente hacemos cumplir esto a través del JavaScript del lado del cliente que puede ser derrotado fácilmente por alguien que esté debidamente motivado.Aplicación de requisitos de fuerza de contraseñas con django.contrib.auth.views.password_change

Parece que no puedo encontrar ninguna información específica sobre la configuración de la validación de la seguridad de contraseñas del lado del servidor utilizando django contrib incorporado en las vistas. Antes de continuar con la reinvención de la rueda, ¿hay una forma adecuada de manejar este requisito?

Respuesta

39

También fui con un formulario personalizado para esto. En urls.py especificar su formulario personalizado:

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

Heredar del PasswordChangeForm e implementar la validación:

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 
+2

No se olvide de '' django.contrib.auth.forms.SetPasswordForm'' –

+5

Para aquellos que quizás no sepan de qué está hablando @uszywieloryba, es la forma utilizada para restablecer las contraseñas. Si usa el código de esta respuesta, simplemente use 'class ValidatingPasswordForm (object):' en lugar de 'class ValidatingPasswordChangeForm (auth.forms.PasswordChangeForm):'. A continuación, defina 'class ValidatingPasswordChangeForm (ValidatingPasswordForm, auth.forms.PasswordChangeForm):' y 'class ValidatingSetPasswordForm (ValidatingPasswordForm, auth.forms.SetPasswordForm):', que contienen solo 'pass'. – Nick

2

Creo que deberías simplemente escribir tu propio validador (o usar RegexValidator, ver: http://docs.djangoproject.com/en/dev/ref/validators/) si usas formularios o escribes algún otro script verificando expresiones regulares. Esto debería ser una tarea simple. Además, no creo que haya ningún mecanismo incorporado, simplemente porque cada persona entiende el concepto de "contraseña segura" un poco diferente.

+0

Voy a mirar en este método. No estoy familiarizado con Django y tenía prisa, así que terminé implementando mi propia versión de la vista django.contrib.auth.views.password_change donde simplemente valido la contraseña antes de permitir que se guarde. Probablemente sea mucho más código de lo necesario. – jslatts

+0

Investigué esto un poco más, y creo que la respuesta correcta involucra validadores, pero igual tendrá que proporcionar un formulario personalizado para usar el validador. Voy a escribir mi respuesta en breve. – jslatts

+0

@jslatts ¿se te ocurrió una respuesta? –

9

que acababa de instalar Django contraseñas y dejar que lo hagan por ti: https://github.com/dstufft/django-passwords

Después que simplemente puede subclase el formulario de registro y reemplazar el campo con un campo de contraseña.

9

Como algunos eludió con los validadores personalizados, aquí está el enfoque me gustaría tener ...

Crear un validador:

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

continuación, agregue el validador para el campo de formulario que está mirando para validar:

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) 
+1

¿Hay algo más que tengo que hacer para usar esto? Agregué este código a admin.py de mi aplicación pero no se está usando. No puedo encontrar la manera de utilizar MySetPasswordForm. –

+0

@LarryMartell, funciona para mí tal como es. ¿Estás seguro de que tienes un campo llamado "new_password1" en tu formulario? Si establece un punto de interrupción en el validador, ¿llega a ese punto de interrupción? –

+0

@TroyGrosfield typo: "contenedor obligatorio" -> "debe contener" – Spaceman

17

Django 1.9 ofrece un sistema incorporado en password validation para ayudar a prevenir el uso de contraseñas débiles por los usuarios. Se habilita modificando la configuración AUTH_PASSWORD_VALIDATORS en nuestro proyecto. Por defecto viene con Django siguientes validadores:

  • UserAttributeSimilarityValidator, que comprueba la similitud entre la contraseña y un conjunto de atributos de usuario.
  • MinimumLengthValidator, que simplemente comprueba si la contraseña cumple con una longitud mínima. Este validador está configurado con una opción personalizada de : ahora requiere que la longitud mínima sea de nueve caracteres, en lugar de los ocho predeterminados.
  • CommonPasswordValidator, que comprueba si la contraseña se produce en una lista de contraseñas comunes. Por por defecto, se compara con una lista incluida de 1000 contraseñas comunes.
  • NumericPasswordValidator, que verifica si la contraseña no es completamente numérica.

Este ejemplo permite a los cuatro incluidos los validadores:

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', 
    }, 
] 
+4

Si estoy creando el usuario a través de una API con el método User.objects.create_user(), ¿cómo consigo que ejecute la validación de la contraseña en esa llamada al método? – Collin

+0

@ Collin - Debe llamar a los métodos de validación usted mismo, no se ejecutan automáticamente solo porque los haya puesto en su configuración. Eche un vistazo a los documentos para [Validación de integración] (https://docs.djangoproject.com/en/dev/topics/auth/passwords/#integrating-validation). – Tony

Cuestiones relacionadas