将自动完成=关闭应用于 Django 密码重置确认表单



我正在使用 Django 2.2 和 Python 3.7

在安全审核之后,我被要求确保应用程序中表单上所有与安全相关的字段都使用 autocomplete="off" 属性呈现。这是否是一种有效且有用的安全措施超出了范围......不幸。到目前为止,我已经通过扩展相关表单来实现这一点。例如,使用密码重置表单(用户在其中输入与帐户关联的电子邮件):

class NoAutocompletePasswordResetForm(PasswordResetForm):
def __init__(self, *args, **kwargs):
super(PasswordResetForm, self).__init__(*args, **kwargs)
self.fields['email'].widget.attrs.update({'autocomplete': 'off'})

然后指示相关的身份验证视图像这样使用它(urls.py):

url(r'^accounts/password_reset/?$', auth_views.PasswordResetView.as_view(form_class=forms.NoAutocompletePasswordResetForm)),

这在密码重置确认视图之前工作正常,该视图使用 SetPasswordForm。那里的第一次尝试是这样的:

url(r'^accounts/reset/(?P<uidb64>[0-9A-Za-z]+)/(?P<token>[0-9A-Za-z-]+)/$', auth_views.PasswordResetConfirmView.as_view(form_class=forms.NoAutocompleteSetPasswordForm)),
class NoAutocompleteSetPasswordForm(SetPasswordForm):
def __init__(self, *args, **kwargs):
super(SetPasswordForm, self).__init__(*args, **kwargs)
self.fields['new_password1'].widget.attrs.update({'autocomplete': 'off'})
self.fields['new_password2'].widget.attrs.update({'autocomplete': 'off'})

然而,这只是在super()行上产生一个TypeError,其中包含__init__() got an unexpected keyword argument 'user'的细节,尽管存在该形式的init的命名user参数,如Django源代码所示。但是为了好玩,我尝试将用户作为位置参数传递,如下所示:

class NoAutocompleteSetPasswordForm(SetPasswordForm):
def __init__(self, *args, **kwargs):
myKwargs = kwargs.copy()
myUser = myKwargs['user']
del myKwargs['user']
myArgs = (*args, myUser)
super(SetPasswordForm, self).__init__(*myArgs, **myKwargs)
self.fields['new_password1'].widget.attrs.update({'autocomplete': 'off'})
self.fields['new_password2'].widget.attrs.update({'autocomplete': 'off'})

通过这种调整,表单可以通过构造,但 Django 在模板渲染过程中出错。特别是,我得到以下堆栈跟踪:

Internal Server Error: /accounts/reset/MjA/set-password/
Traceback (most recent call last):
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 829, in _resolve_lookup
current = current[bit]
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangoformsboundfield.py", line 66, in __getitem__
raise TypeError
TypeError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangocorehandlersexception.py", line 34, in inner
response = get_response(request)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangocorehandlersbase.py", line 145, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangocorehandlersbase.py", line 143, in _get_response
response = response.render()
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplateresponse.py", line 106, in render
self.content = self.rendered_content
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplateresponse.py", line 83, in rendered_content
content = template.render(context, self._request)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebackendsdjango.py", line 61, in render
return self.template.render(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 171, in render
return self._render(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 163, in _render
return self.nodelist.render(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 937, in render
bit = node.render_annotated(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 904, in render_annotated
return self.render(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatedefaulttags.py", line 309, in render
return nodelist.render(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 937, in render
bit = node.render_annotated(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 904, in render_annotated
return self.render(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 987, in render
output = self.filter_expression.resolve(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 671, in resolve
obj = self.var.resolve(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 796, in resolve
value = self._resolve_lookup(context)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangotemplatebase.py", line 837, in _resolve_lookup
current = getattr(current, bit)
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangoformsboundfield.py", line 74, in errors
return self.form.errors.get(self.name, self.form.error_class())
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangoformsforms.py", line 180, in errors
self.full_clean()
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangoformsforms.py", line 381, in full_clean
self._clean_fields()
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangoformsforms.py", line 393, in _clean_fields
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
File "C:UsersBenDocumentsDeloreandelorean_env_37libsite-packagesdjangoformswidgets.py", line 258, in value_from_datadict
return data.get(name)
AttributeError: 'User' object has no attribute 'get'

那么,如何让这个表单使用 autocomplete='off' 渲染呢?

经过多次拔头发,我开始工作。从这里汲取灵感,并基于我一度收到有关意外用户参数的错误这一事实,我将表单更改为以下内容:

class NoAutocompleteSetPasswordForm(SetPasswordForm):
def __init__(self, user, *args, **kwargs):
self.user = user
super(SetPasswordForm, self).__init__(*args, **kwargs)
self.fields['new_password1'].widget.attrs.update({'autocomplete': 'off'})
self.fields['new_password2'].widget.attrs.update({'autocomplete': 'off'})

现在,它会根据需要使用自动完成属性呈现页面。

最新更新