Django使用错误的凭据登录返回200而不是401

时间:2014-09-15 00:51:22

标签: python django http-status-code-401

这是一个非常直接的测试,但我似乎无法做到正确。

我想检查哪些用户可以登录并执行操作(它是更大的测试套件的一部分),但第一步会导致一些问题。

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

有关其他上下文,以下是我管理登录/注销网址的方式:

urlpatterns = patterns('',
    # Examples:
    url(r'^accounts/login/?$', 'django.contrib.auth.views.login'),
    url(r'^accounts/logout/?$', 'django.contrib.auth.views.logout',
        {'next_page': '/'}),

3 个答案:

答案 0 :(得分:6)

网络社区中存在一些关于对凭据失败的正确回应是什么的争论。 (例如,此处&#39; sa Wordpress ticket关于从200切换到401。)Django选择返回200响应以及重新呈现的表单。< / p>

在我看来,这是正确的方法。 401403响应表示用户没有访问资源(URL)的权限。但在这种情况下,资源是登录点,您不需要需要凭据才能访问该资源;根据定义,它可供所有用户使用。所以基本上这种情况与任何其他表单验证没有什么不同 - 服务器正在检查它发送的输入,如果它们无效,它会返回200响应以及表单和错误消息。< / p>

答案 1 :(得分:2)

我刚刚查看了Django源代码以及为什么在行52之后的this函数中的原因。如果表单无效,login视图将返回TemplateResponse,只返回同一页面并呈现包含错误的表单。

答案 2 :(得分:1)

您可以通过以下方式轻松自定义此行为:

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

,您将需要更改相应的网址:

    path("accounts/login/", views.LoginView.as_view(), name="login"),
    path("accounts/", include("django.contrib.auth.urls")),