2011-03-07 72 views
41

我們有一個Django應用程序,它需要特定級別的密碼複雜性。我們目前通過客戶端JavaScript來執行此操作,這可能很容易被適當動機的人擊敗。使用django.contrib.auth.views.password_change實施密碼強度要求

我似乎無法找到有關使用視圖中內置的django contrib設置服務器端密碼強度驗證的任何特定信息。在我重新發明車輪之前,是否有適當的方法來處理這個要求?

回答

39

我也去了一個自定義的形式。從PasswordChangeForm

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

繼承,並實現驗證:在urls.py指定您的自定義窗體

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

不要忘記''django.contrib.auth.forms.SetPasswordForm'' – 2013-03-15 08:43:01

+5

對於那些可能不知道@uszywieloryba在說什麼的人,這是用於密碼重置的形式。如果你使用這個答案的代碼,只需使用'class ValidatingPasswordForm(object):'而不是'class ValidatingPasswordChangeForm(auth.forms.PasswordChangeForm):'。然後定義'class ValidatingPasswordChangeForm(ValidatingPasswordForm,auth.forms.PasswordChangeForm):'和'Class ValidatingSetPasswordForm(ValidatingPasswordForm,auth.forms.SetPasswordForm):',都只包含'pass'。 – Nick 2014-05-23 20:56:00

2

如果您使用窗體或爲正則表達式編寫一些其他腳本檢查,我認爲您應該編寫自己的驗證器(或使用RegexValidator,請參閱:http://docs.djangoproject.com/en/dev/ref/validators/)。這應該是一個簡單的任務。我也不認爲有任何內建機制,只是因爲每個人都明白「強密碼」的概念有點不同。

+0

我會考慮這種方法。我對Django並不熟悉,而且我很匆忙,所以我最終實現了我自己的django.contrib.auth.views.password_change視圖版本,我只是在允許它保存之前驗證密碼。它可能比需要更多的代碼。 – jslatts 2011-03-08 00:20:24

+0

我對此進行了一些研究,我認爲正確的答案確實涉及到驗證器,但您仍然需要提供一個自定義表單來使用驗證器。我很快就會寫出我的答案。 – jslatts 2011-03-09 21:08:59

+0

@jslatts你有沒有想出答案? – 2011-06-07 16:04:50

9

至於一些躲避到與自定義驗證,這裏是我採取的辦法......

創建驗證:

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

然後驗證添加到您所希望的表單字段驗證:

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

我還有什麼需要做的?我將這段代碼添加到我的應用的admin.py中,但沒有得到使用。我無法弄清楚如何使用MySetPasswordForm。 – 2015-04-10 19:30:02

+0

@LarryMartell,它爲我工作。你確定你的表單中有一個名爲「new_password1」的字段嗎?如果你在驗證器中設置了一個斷點,它是否會觸發該斷點? – 2016-02-12 17:07:57

+0

@TroyGrosfield錯字:「必須容器」 - >「必須包含」 – Spaceman 2016-03-27 21:15:55

17

的Django 1.9提供了一個內置的password validation,以幫助防止弱密碼的用戶的使用。它可以通過修改我們項目中的AUTH_PASSWORD_VALIDATORS設置來啓用。缺省情況下Django帶有以下驗證:

  • UserAttributeSimilarityValidator,檢查密碼和一組用戶的屬性 之間的相似度。
  • MinimumLengthValidator,它只是檢查密碼 是否符合最小長度。該驗證器配置了一個自定義的 選項:它現在要求最小長度爲9個字符,而不是默認的八個字符,即 。
  • CommonPasswordValidator,它檢查 密碼是否出現在普通密碼列表中。默認情況下,它與 相比,包含1000個通用密碼的列表。
  • NumericPasswordValidator,它檢查密碼是否不是 完全數字。

本示例啓用所有四個包括驗證:

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

如果我使用User.objects.create_user()方法通過API創建用戶,如何讓它在該方法調用上運行密碼驗證? – Collin 2016-08-16 21:51:54

+0

@Collin - 你需要自己調用驗證方法,它們不會自動運行,因爲你已經把它們放在你的設置中。查看[集成驗證]文檔(https://docs.djangoproject.com/en/dev/topics/auth/passwords/#integrating-validation)。 – Tony 2017-02-28 22:15:45