Ste*_*teg 5 python security authentication django
在django中使用标准身份验证模块时,失败的用户身份验证不明确.也就是说,似乎无法区分以下两种情况:
我想我想在这两种情况下向用户显示相应的消息,而不是单个"用户名或密码无效......".
任何人都有使用简单方法的经验.问题的症结似乎是在最低级别 - 在django.contrib.auth.backends.ModelBackend类中.此类的authenticate()方法(以用户名和密码作为参数)仅在身份验证成功时返回User对象,如果身份验证失败则返回None.鉴于此代码处于最低级别(好,最低级别高于数据库代码),绕过它似乎很多代码被抛弃了.
简单地实现新的身份验证后端并将其添加到AUTHENTICATION_BACKENDS设置是最好的方法吗?可以实现返回(User,Bool)元组的后端,其中如果用户名不存在,则User对象仅为None,如果密码正确,则Bool仅为True.但是,这会破坏后端与django.contrib.auth.authenticate()方法的约定(记录为在成功验证时返回User对象,否则为None).
也许,这一切都是无所顾忌?无论用户名或密码是否不正确,用户可能无论如何都必须转到"忘记密码"页面,所以这可能都是学术性的.我只是忍不住感觉,不过......
编辑:
关于我选择的答案的评论:我选择的答案是实现此功能的方法.下面还有另一个答案,讨论了这样做的潜在安全隐患,我也将其视为提名的答案.但是,我提名的答案解释了如何实现此功能.基于安全性的答案讨论了是否应该实现这个功能,这实际上是一个不同的问题.
Dan*_*man 19
你真的不想区分这两种情况.否则,您将为潜在的黑客提供关于用户名是否有效的线索 - 这对获取欺诈性登录有重大帮助.
这不是后端的功能,只是身份验证表单的功能。只需重写表单即可显示每个字段所需的错误。编写一个使用新表单的登录视图,并将其设为默认登录 URL。(实际上,我刚刚在 Django 最近的提交中看到,您现在可以将自定义表单传递到登录视图,因此这更容易完成)。这大约需要 5 分钟的时间。你需要的一切都在 django.contrib.auth 中。
此处澄清的是当前的形式:
class AuthenticationForm(forms.Form):
"""
Base class for authenticating users. Extend this to get a form that accepts
username/password logins.
"""
username = forms.CharField(label=_("Username"), max_length=30)
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
def __init__(self, request=None, *args, **kwargs):
"""
If request is passed in, the form will validate that cookies are
enabled. Note that the request (a HttpRequest object) must have set a
cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before
running this validation.
"""
self.request = request
self.user_cache = None
super(AuthenticationForm, self).__init__(*args, **kwargs)
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username, password=password)
if self.user_cache is None:
raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
elif not self.user_cache.is_active:
raise forms.ValidationError(_("This account is inactive."))
# TODO: determine whether this should move to its own method.
if self.request:
if not self.request.session.test_cookie_worked():
raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
return self.cleaned_data
def get_user_id(self):
if self.user_cache:
return self.user_cache.id
return None
def get_user(self):
return self.user_cache
Run Code Online (Sandbox Code Playgroud)
添加:
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
raise forms.ValidationError("The username you have entered does not exist.")
return username
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6125 次 |
| 最近记录: |