弱密码校验是 Django 1.9 新功能之一,可以通过 settings 中的 AUTH_PASSWORD_VALIDATORS
来开启。
以下是四个自带的校验器,当然也可以自己写校验器,只需要按照下述格式添加进去就可以做统一校验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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' , }, ]
并不是直接 set_password 就会校验,而是需要在 set_password 前手动调用,用法如下
1 2 3 from django.contrib.auth.password_validation import validate_passwordvalidate_password(password, user=None , password_validators=None )
其中
password 是 raw string 的 password 字符串
user 是检查的用户实例,非必须。如果 validator 需要根据 user 实例做判断,那么就需要传
password_validators 是 list,包含所有需要校验的 validator,不指定的话默认校验所有 settings.py 中指定的 validator
如果所有 validator 都通过,返回 None;否则 raise 包含所有错误消息的 ValidationError。
实战:在 form 中校验用户的两次密码输入
1 2 3 4 5 6 7 8 9 class PasswordInitForm (forms.Form): password = RepeatCharField() def clean_password (self ): validate_password(self .cleaned_data['password' ]) return self .cleaned_data['password' ]
我的 view 是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class PasswordInitView(LoginRequiredMixin, TemplateView) : template_name = 'user/password_init.html' @json_resp() def post(self, request): form = PasswordInitForm(request .POST) result = {} if form.is_valid() : request.user.set_password(form .cleaned_data ['password ']) request.user.need_reset_password = False request.user.save() result['next '] = get_redirect_url(request , 'POST') else : result = Error(form .errors ) return result
附上 RepeatCharField 的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class RepeatCharWidget (MultiWidget): def __init__ (self ): widgets = ( TextInput(), TextInput(), ) super (RepeatCharWidget, self ).__init__(widgets) class RepeatCharField (MultiValueField): def __init__ (self , *args, **kwargs ): fields = ( CharField(), CharField(), ) if 'error_messages' not in kwargs or 'invalid' not in kwargs.get('error_messages' ): if 'error_messages' not in kwargs: kwargs['error_messages' ] = {} kwargs['error_messages' ].update({'invalid' : ugettext_lazy('Invalid repeat input' )}) kwargs['widget' ] = kwargs.pop('widget' , RepeatCharWidget()) super (RepeatCharField, self ).__init__(fields, *args, **kwargs) def compress (self , data_list ): return data_list[0 ] def clean (self , value ): if value[0 ] != value[1 ]: raise forms.ValidationError(getattr(self , 'error_messages' , {}).get('invalid' , ugettext_lazy('Repeat input should be the same' ))) return super (RepeatCharField, self ).clean(value)