Django Rest Framework - 为什么尝试使用不正确的凭据登录用户时返回 200 状态代码?

use*_*875 4 django angularjs django-rest-framework django-rest-auth

这是我的 URLs.py:

url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
Run Code Online (Sandbox Code Playgroud)

我的主页上有一个表单,用户可以在其中键入用户名和密码。当提交按钮被点击时,AngularJS 使用用户对象(用户名和密码)向“api-auth/login/”发送一个 POST 请求:

$http.post("/api-auth/login/", self.loginuser)
    .error(function(data, status, headers, config) {
        console.log(data);
     });
Run Code Online (Sandbox Code Playgroud)

当用户提交不正确的用户名和密码(用户名和密码不存在或不匹配)时,Django Rest Framework 返回 200 OK 而不是 204 No Content、404 或 401 Unauthorized(在这篇文章中,它说 401是要返回的正确状态代码:如果用户尝试使用不正确的用户名/密码但格式正确登录,要返回的适当 HTTP 状态代码是什么?)。

根据这里:http : //www.w3.org/Protocols/rfc2616/rfc2616-sec9.html在第 9.5 节 POST 中,它说“在这种情况下,200(OK)或 204(无内容)是适当的响应状态,取决于响应是否包含描述结果的实体。”

如果数据存在,我会处理错误并记录数据(我在 JS 中做了 console.log(data)),但没有记录数据,这意味着(据我了解)没有数据发送/响应不包含描述的实体结果。

那么 DjangoRestFramework 为什么会返回 200 而不是 204 No Content(或者 404 或 401,根据我链接到的其他 SO 帖子应该返回什么)?

spe*_*ras 6

您的问题中混杂了几件事。首先,您使用的技术观点,其次是您解释答案的方式。

1) 意见

这是一个快速的。您通过将数据发送到/api-auth/login/DRF 的可浏览 API的登录视图来使用的视图。该视图实际上是 Django 的auth应用程序 ( django.contrib.auth.views.login)附带的视图,它假定它正在与用户打交道,手动浏览 API。

即:调用它GET构建一个空的 html 表单,发送回表单POST将触发表单验证,这可能会导致表单重新显示(包含文档的 200 Ok),或者要发送回的重定向(302发现内容为空)。

这就是您的数据为空的原因:服务器发送一个 HTML 文档,而您的 angular 可能试图解析一些 JSON 对象。

您使用的表单视图绝对不打算从脚本中调用。这可以做到,但您需要相应地处理结果,这意味着分析返回的 html 页面以查找错误消息。乱。

如果您想从脚本轻松访问它,您应该构建自己的登录视图。

2) 文档 vs 请求

您在这里处理两个不同级别的语义。

  1. 请求的意义。
  2. 请求中所附文件的含义。

HTTP 错误代码在请求的上下文中是有意义的。它们发生在较低的级别。例如,返回 401 代码意味着“在执行此请求之前需要有效的身份验证凭据”

所以在这里,这基本上意味着我处理您的登录请求之前,您必须拥有有效的身份验证凭据”

这可能有意义,但仅限于您有两层身份验证的上下文。在让您的第二层登录请求通过之前,您需要拥有对第一层有效的身份验证凭据。在这种情况下,如果您尝试使用第二层登录而第一层无法识别,则可能会得到 401。

那么,REST 是如何适应的呢?

REST的概念,当应用于 HTTP 时,是尝试匹配请求级语义和文档级语义。它特别适合,因为每个 REST 概念都有一个匹配的 HTTP 动词,HTTP 是可缓存的,客户端-服务器,......和......无状态

无状态意味着 HTTP 和 REST 都没有登录的概念。 登录是一种抽象,这通常意味着我们使用如下所示的工作流:

  1. 我们对某个端点进行身份验证(登录/密码、质询、oauth 等)。
  2. 端点返回一些授权令牌
  3. 我们将授权令牌与每个下一个请求发送到服务器。

但事实是,每个请求都必须得到服务器的授权。也就是说,服务器总是先授权请求,然后再查看里面的内容。如果此步骤失败,则 401 是一个适当的响应。

除了步骤#1。此请求没有授权步骤。必须对其进行处理,必须检索和检查登录名/密码,并且根据结果,服务器可能会决定发回授权令牌。

那么,如果它选择不这样做,什么样的错误代码是合适的?嗯,有几个你可以选择:

  • 200 好的。登录请求已成功处理并产生错误消息,这是带有结果的文档。然后,您的脚本将读取文档(例如,可以是 JSON 对象)以查看它是否有错误或授权令牌。
  • 204 无内容。登录请求已成功处理,但什么也没产生,当然也没有授权令牌。奇怪的选择,但正确。
  • 400 错误请求。登录请求未成功处理。

唯一可以肯定的是,401 不是一个选项。401 表示不允许您尝试登录。不是登录失败。


Fer*_*iro 5

以我的拙见,您在这里将业务概念与协议问题混合在一起。

登录方法不应返回 401(未经授权),因为它的先决条件是用户(显然)尚未经过授权/身份验证。因此,如果请求以正确的方式发出(从语法上来说),尽管用户凭据不正确(业务概念),响应应该是 200(协议),即请求已被接受并得到正确处理。当然,响应正文将确定是否成功登录。

因此,毕竟,您尝试记录应用程序错误,而实际上它是业务层错误(用户根据您的数据库输入了错误的值)。得到它?