django 1.7 中的自定义密码验证
custom password validation in django 1.7
我正在尝试向创建用户和更改密码管理表单添加自定义密码验证。我没有在 django 文档中看到任何有关如何执行此操作的信息。我在 SO: Enforcing password strength requirements with django.contrib.auth.views.password_change 上找到了这个 post,它给出了 2 个解决方案。我都试过了,但都不适合我。
这是我现在的应用程序 admin.py:
def validate_password_strength(value):
"""Validates that a password is as least 10 characters long and has at least
2 digits and 1 Upper case letter.
"""
min_length = 10
if len(value) < min_length:
raise ValidationError(_('Password must be at least {0} characters '
'long.').format(min_length))
# check for 2 digits
if sum(c.isdigit() for c in value) < 2:
raise ValidationError(_('Password must container at least 2 digits.'))
# check for uppercase letter
if not any(c.isupper() for c in value):
raise ValidationError(_('Password must container at least 1 uppercase letter.'))
class MySetPasswordForm(SetPasswordForm):
def __init__(self, *args, **kwargs):
super(MySetPasswordForm, self).__init__(*args, **kwargs)
self.fields['password1'].validators.append(validate_password_strength)
但我不知道如何使用 MySetPasswordForm。
我尝试了几种不同的方法。首先我这样做了:
class UserAdmin(UserAdmin):
form = MySetPasswordForm
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
我得到了这个错误:
<class 'elex_apis.energy.webservice.admin.UserAdmin'>: (admin.E016) The value of 'form' must inherit from 'BaseModelForm'.
然后我将 MySetPasswordForm 更改为继承自 BaseModelForm 然后我得到了这个错误:
__init__() missing 1 required positional argument: 'user'
然后我添加了用户参数,所以现在 MySetPasswordForm 看起来像这样:
class MySetPasswordForm(BaseModelForm):
def __init__(self, user, *args, **kwargs):
super(MySetPasswordForm, self).__init__(user, *args, **kwargs)
self.fields['password1'].validators.append(validate_password_strength)
但是还是报了和之前一样的错误。
我不敢相信添加密码验证器这么难。这一定是一个非常普遍的需求,所以很明显我一定遗漏了一些简单的东西。任何人都可以在这里提供一些帮助。
最简单的方法是继承原来的UserAdmin
并覆盖change_password_form
。
示例:
from django.contrib.auth import models as auth_models
from django.contrib.auth import admin as auth_admin
from django.contrib.auth import forms as auth_forms
from django.core.exceptions import ValidationError
def validate_password_strength(value):
"""Validates that a password is as least 10 characters long and has at least
2 digits and 1 Upper case letter.
"""
min_length = 10
if len(value) < min_length:
raise ValidationError(_('Password must be at least {0} characters '
'long.').format(min_length))
# check for 2 digits
if sum(c.isdigit() for c in value) < 2:
raise ValidationError(_('Password must container at least 2 digits.'))
# check for uppercase letter
if not any(c.isupper() for c in value):
raise ValidationError(_('Password must container at least 1 uppercase letter.'))
return value
class AdminPasswordChangeForm(auth_forms.AdminPasswordChangeForm):
def clean_password1(self):
return validate_password_strength(self.cleaned_data['password1'])
class UserCreationForm(auth_forms.UserCreationForm):
def clean_password1(self):
return validate_password_strength(self.cleaned_data['password1'])
class UserAdmin(auth_admin.UserAdmin):
change_password_form = AdminPasswordChangeForm
add_form = UserCreationForm
# Re-register UserAdmin
admin.site.unregister(auth_models.User)
admin.site.register(auth_models.User, UserAdmin)
另一种方法是创建一个 validators.py 文件,并在其中根据对象创建您自己的 类 并在输入密码失败时引发 ValidationError。更多内容 here.
import re
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
class NumberValidator(object):
def validate(self, password, user=None):
if not re.findall('\d', password):
raise ValidationError(
_("The password must contain at least 1 digit, 0-9."),
code='password_no_number',
)
def get_help_text(self):
return _(
"Your password must contain at least 1 digit, 0-9."
)
class UppercaseValidator(object):
def validate(self, password, user=None):
if not re.findall('[A-Z]', password):
raise ValidationError(
_("The password must contain at least 1 uppercase letter, A-Z."),
code='password_no_upper',
)
def get_help_text(self):
return _(
"Your password must contain at least 1 uppercase letter, A-Z."
)
使用正确的验证器虚线路径更新 AUTH_PASSWORD_VALIDATORS 设置:
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 12, }
},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', },
{'NAME': 'my.project.validators.NumberValidator',
'OPTIONS': {
'min_digits': 3, }},
{'NAME': 'my.project.validators.UppercaseValidator', },
]
我正在尝试向创建用户和更改密码管理表单添加自定义密码验证。我没有在 django 文档中看到任何有关如何执行此操作的信息。我在 SO: Enforcing password strength requirements with django.contrib.auth.views.password_change 上找到了这个 post,它给出了 2 个解决方案。我都试过了,但都不适合我。
这是我现在的应用程序 admin.py:
def validate_password_strength(value):
"""Validates that a password is as least 10 characters long and has at least
2 digits and 1 Upper case letter.
"""
min_length = 10
if len(value) < min_length:
raise ValidationError(_('Password must be at least {0} characters '
'long.').format(min_length))
# check for 2 digits
if sum(c.isdigit() for c in value) < 2:
raise ValidationError(_('Password must container at least 2 digits.'))
# check for uppercase letter
if not any(c.isupper() for c in value):
raise ValidationError(_('Password must container at least 1 uppercase letter.'))
class MySetPasswordForm(SetPasswordForm):
def __init__(self, *args, **kwargs):
super(MySetPasswordForm, self).__init__(*args, **kwargs)
self.fields['password1'].validators.append(validate_password_strength)
但我不知道如何使用 MySetPasswordForm。
我尝试了几种不同的方法。首先我这样做了:
class UserAdmin(UserAdmin):
form = MySetPasswordForm
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
我得到了这个错误:
<class 'elex_apis.energy.webservice.admin.UserAdmin'>: (admin.E016) The value of 'form' must inherit from 'BaseModelForm'.
然后我将 MySetPasswordForm 更改为继承自 BaseModelForm 然后我得到了这个错误:
__init__() missing 1 required positional argument: 'user'
然后我添加了用户参数,所以现在 MySetPasswordForm 看起来像这样:
class MySetPasswordForm(BaseModelForm):
def __init__(self, user, *args, **kwargs):
super(MySetPasswordForm, self).__init__(user, *args, **kwargs)
self.fields['password1'].validators.append(validate_password_strength)
但是还是报了和之前一样的错误。
我不敢相信添加密码验证器这么难。这一定是一个非常普遍的需求,所以很明显我一定遗漏了一些简单的东西。任何人都可以在这里提供一些帮助。
最简单的方法是继承原来的UserAdmin
并覆盖change_password_form
。
示例:
from django.contrib.auth import models as auth_models
from django.contrib.auth import admin as auth_admin
from django.contrib.auth import forms as auth_forms
from django.core.exceptions import ValidationError
def validate_password_strength(value):
"""Validates that a password is as least 10 characters long and has at least
2 digits and 1 Upper case letter.
"""
min_length = 10
if len(value) < min_length:
raise ValidationError(_('Password must be at least {0} characters '
'long.').format(min_length))
# check for 2 digits
if sum(c.isdigit() for c in value) < 2:
raise ValidationError(_('Password must container at least 2 digits.'))
# check for uppercase letter
if not any(c.isupper() for c in value):
raise ValidationError(_('Password must container at least 1 uppercase letter.'))
return value
class AdminPasswordChangeForm(auth_forms.AdminPasswordChangeForm):
def clean_password1(self):
return validate_password_strength(self.cleaned_data['password1'])
class UserCreationForm(auth_forms.UserCreationForm):
def clean_password1(self):
return validate_password_strength(self.cleaned_data['password1'])
class UserAdmin(auth_admin.UserAdmin):
change_password_form = AdminPasswordChangeForm
add_form = UserCreationForm
# Re-register UserAdmin
admin.site.unregister(auth_models.User)
admin.site.register(auth_models.User, UserAdmin)
另一种方法是创建一个 validators.py 文件,并在其中根据对象创建您自己的 类 并在输入密码失败时引发 ValidationError。更多内容 here.
import re
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
class NumberValidator(object):
def validate(self, password, user=None):
if not re.findall('\d', password):
raise ValidationError(
_("The password must contain at least 1 digit, 0-9."),
code='password_no_number',
)
def get_help_text(self):
return _(
"Your password must contain at least 1 digit, 0-9."
)
class UppercaseValidator(object):
def validate(self, password, user=None):
if not re.findall('[A-Z]', password):
raise ValidationError(
_("The password must contain at least 1 uppercase letter, A-Z."),
code='password_no_upper',
)
def get_help_text(self):
return _(
"Your password must contain at least 1 uppercase letter, A-Z."
)
使用正确的验证器虚线路径更新 AUTH_PASSWORD_VALIDATORS 设置:
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 12, }
},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', },
{'NAME': 'my.project.validators.NumberValidator',
'OPTIONS': {
'min_digits': 3, }},
{'NAME': 'my.project.validators.UppercaseValidator', },
]