【发布时间】:2019-07-22 19:49:58
【问题描述】:
我将 Django 2.2 与 Python 3.7 一起使用
在进行安全审核后,我被要求确保应用程序中表单上所有与安全相关的字段都使用 autocomplete="off" 属性呈现。这是否是一个有效和有用的安全措施超出了范围......不幸的是。到目前为止,我已经通过扩展相关表格来实现这一点。例如,使用 PasswordResetForm(用户输入与帐户关联的电子邮件):
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 的参数,如 in the Django source 所示。但是为了有趣,我尝试将用户作为位置参数传递,如下所示:
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:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 829, in _resolve_lookup
current = current[bit]
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\forms\boundfield.py", line 66, in __getitem__
raise TypeError
TypeError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\core\handlers\base.py", line 145, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\core\handlers\base.py", line 143, in _get_response
response = response.render()
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\response.py", line 106, in render
self.content = self.rendered_content
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\response.py", line 83, in rendered_content
content = template.render(context, self._request)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\backends\django.py", line 61, in render
return self.template.render(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 171, in render
return self._render(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 163, in _render
return self.nodelist.render(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 937, in render
bit = node.render_annotated(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 904, in render_annotated
return self.render(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\defaulttags.py", line 309, in render
return nodelist.render(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 937, in render
bit = node.render_annotated(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 904, in render_annotated
return self.render(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 987, in render
output = self.filter_expression.resolve(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 671, in resolve
obj = self.var.resolve(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 796, in resolve
value = self._resolve_lookup(context)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\template\base.py", line 837, in _resolve_lookup
current = getattr(current, bit)
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\forms\boundfield.py", line 74, in errors
return self.form.errors.get(self.name, self.form.error_class())
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\forms\forms.py", line 180, in errors
self.full_clean()
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\forms\forms.py", line 381, in full_clean
self._clean_fields()
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\forms\forms.py", line 393, in _clean_fields
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
File "C:\Users\Ben\Documents\Delorean\delorean_env_37\lib\site-packages\django\forms\widgets.py", line 258, in value_from_datadict
return data.get(name)
AttributeError: 'User' object has no attribute 'get'
那么,如何让这个表单在 autocomplete='off' 的情况下呈现?
【问题讨论】:
-
myKwargs = dict(**kwargs)kwargs 已经是字典了。 -
我这样做更多是为了获得一份副本而不是演员,但很好。我已将其更改为 kwargs.copy()。结果没有变化
标签: python django python-3.x django-forms