本文目录


    Django 弱密码校验那些事

    弱密码校验是 Django 1.9 新功能之一,可以通过 settings 中的 AUTH_PASSWORD_VALIDATORS 来开启。 以下是四个自带的校验器,当然也可以自己写校验器,只需要按照下述格式添加进去就可以做统一校验。

    # settings.py
    AUTH_PASSWORD_VALIDATORS = [
        {
            # 用户属性相似验证,检查密码和一组用户的属性的相似性 
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            # 最小长度验证,最小接受长度为 9
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
            'OPTIONS': {
                'min_length': 9,
            }
        },
        {
            # 常见密码验证,这个检查器会对比常用的弱密码,这些常用密码被 gzip 打包储存在 `django/contrib/auth/common-passwords.txt.gz` 中 
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            # 纯数字密码验证 
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]

    并不是直接 set_password 就会校验,而是需要在 set_password 前手动调用,用法如下

    from django.contrib.auth.password_validation import validate_password
    
    validate_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 中校验用户的两次密码输入

    class PasswordInitForm(forms.Form):
        # RepeatCharField 是自定义的一个 MultiValueField
        # 它接受两个 CharField 输入,并检查其是否一致 
        # 如果不一致,raise ValidationError;否则返回相同的 CharField 值 
        password = RepeatCharField()
    
        def clean_password(self):
            validate_password(self.cleaned_data['password'])
            return self.cleaned_data['password']

    我的 view 是这样的

    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 的代码

    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)

    Django 弱密码校验那些事

    文章作者:  BigYoung
    版权声明:  本网站所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 BigYoung !