使用错误凭据的 Django 登录返回 200 而不是 401
Posted
技术标签:
【中文标题】使用错误凭据的 Django 登录返回 200 而不是 401【英文标题】:Django login with wrong credentials returns 200 not 401 【发布时间】:2014-11-08 11:18:41 【问题描述】:这是一个非常直接的测试,但我似乎做错了。
我想检查哪些用户可以登录并执行操作(这是更大的测试套件的一部分),但第一步会导致一些问题。
class SuperUserTest(TestCase):
def setUp(self):
self.client = Client()
self.su = User.objects.create_superuser('super','','the_correct_password')
def test_su_can_login(self):
response = self.client.post(reverse('django.contrib.auth.views.login'),
'username': 'super', 'password': 'the_wrong_password')
self.assertEqual(response.status_code,401)
# Success redirects to the homepage, so its 302 not 200
response = self.client.post(reverse('django.contrib.auth.views.login'),
'username': 'super', 'password': 'the_correct_password')
self.assertEqual(response.status_code,302)
当我运行测试时,我得到:
(my_app)00:20 ~/my_app (master)$ ./manage.py test my_app.SuperUserTest
Creating test database for alias 'default'...
F
======================================================================
FAIL: test_su_can_login (my_app.SuperUserTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "./my_app/tests.py", line 341, in test_su_can_login
self.assertEqual(response.status_code,401)
AssertionError: 200 != 401
----------------------------------------------------------------------
Ran 1 test in 1.180s
FAILED (failures=1)
Destroying test database for alias 'default'...
为什么 django 在我错误登录时返回 HTTP 代码 200
?
对于其他上下文,这是我管理登录/注销 url 的方式:
urlpatterns = patterns('',
# Examples:
url(r'^accounts/login/?$', 'django.contrib.auth.views.login'),
url(r'^accounts/logout/?$', 'django.contrib.auth.views.logout',
'next_page': '/'),
【问题讨论】:
【参考方案1】:网络社区中存在一些关于对凭据失败的正确响应是什么的争论。例如,这是一个关于从 200
切换到 401
的 Wordpress ticket。在 Stack Overflow 上,您可以找到 some 推荐 200
和 some 推荐 401
。
Django 选择返回 200
响应以及重新呈现的表单。
在我看来,这是正确的方法。 401
或 403
响应表示用户没有访问资源 (URL) 的权限。但在这种情况下,资源是登录点,您不需要 凭据来访问它;根据定义,它可供所有用户使用。所以本质上,这种情况与任何其他表单验证没有什么不同——服务器正在检查它发送的输入,如果它们无效,它会返回 200
响应以及表单和错误消息。
【讨论】:
【参考方案2】:我刚刚浏览了 Django 源代码,原因在于 52
行之后的 this 函数。如果表单无效,login
视图返回一个TemplateResponse
,只是返回到同一页面并呈现带有错误的表单。
【讨论】:
【参考方案3】:您可以通过以下方式轻松自定义此行为:
from django.contrib.auth.views import LoginView
class LoginView(LoginView):
def form_invalid(self, form):
response = super().form_invalid(form)
response.status_code = 401
return response
你需要更改相应的url:
path("accounts/login/", views.LoginView.as_view(), name="login"),
path("accounts/", include("django.contrib.auth.urls")),
【讨论】:
你不见了:template_name = 'admin/login.html'
否则说 login.html 不见了。以上是关于使用错误凭据的 Django 登录返回 200 而不是 401的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core HttpClient 请求在 webapi 返回 406 时返回 200