ChatGPT解决这个技术问题 Extra ChatGPT

如果用户尝试使用不正确的用户名/密码但格式正确登录,则返回的适当 HTTP 状态代码是什么?

此处发布了一个类似的问题:What's an appropriate HTTP status code to return by a REST API service for a validation failure?

上面线程中的答案指出“例如,如果 URI 应该具有 ISO-8601 日期,而您发现它的格式错误或指的是 2 月 31 日,那么您将返回 HTTP 400。如果您期望实体主体中格式良好的 XML,但无法解析。”

但是,如果用户提交了正确格式的数据会发生什么?我的意思是,用户为用户名和密码提交了一个纯字母字符串/文本(这对我的应用程序完全有效)。唯一的问题是密码与用户名不匹配。在这种情况下,400 将是不正确的,因为它是完全有效的语法并且格式正确。

401 将是不正确的(如此处建议的:Which HTTP status code to say username or password were incorrect?),因为用户没有尝试访问任何页面,他只是尝试登录并输入了不匹配的数据。

如果您回顾我链接到的第一篇文章,第二个答案指出 422 是正确的响应(对我来说看起来是正确的),但是,我使用的是 Django Rest Framework 并且 422 不是状态代码的一部分(a可以在此处找到属于 DRF 一部分的状态代码列表:http://www.django-rest-framework.org/api-guide/status-codes/#client-error-4xx

404 看起来也不正确,因为数据被成功接受并且没有被拒绝。

话虽如此,应该使用的真正正确的响应是什么?


C
Community

如果您严格使用 RFC 7235 为您的 REST API 提供的 HTTP 身份验证框架,正确的 HTTP 代码实际上应该是 401。来自 the RFC

401(未授权)状态码表示该请求尚未应用,因为它缺少目标资源的有效身份验证凭据。生成 401 响应的服务器必须发送一个 WWW-Authenticate 头字段(第 4.1 节),其中包含至少一个适用于目标资源的质询。如果请求包含身份验证凭据,则 401 响应表明这些凭据的授权已被拒绝。用户代理可以使用新的或替换的授权头字段重复请求(第 4.2 节)。

您的 REST API 应使用某种类型的 authentication scheme,以便向您的客户端返回有效的 401 响应。

RFC 7235,第 4 页的另一个相关部分:

在收到对省略凭据、包含无效凭据(例如,密码错误)或部分凭据(例如,当身份验证方案需要多次往返时)的受保护资源的请求时,源服务器应该发送 401(未授权) 响应,其中包含一个 WWW-Authenticate 标头字段,其中至少有一个(可能是新的)质询适用于所请求的资源。

更高级别的响应,例如为视觉用户呈现的登录页面(通过 302 从受保护的资源重定向),最好使用 200 状态代码(例如,根据@KernelDeimos 的答案)。由于登录页面通常是它们自己的资源(例如 /login?redirect=original-resource),因此未经身份验证的用户仍然有权查看此页面,即使他们提供了不正确的用户名/密码。然后,您将经过身份验证的用户重定向回资源,此时如果允许,将显示 200,如果禁止用户查看资源,则显示 403。

401 可以与可视登录页面发挥作用的领域是一个前端库,它使用 XHR 请求利用 REST API,然后将来自 REST API 的 401 响应转发回登录页面上有意义的格式。


哦,你是对的,401 是我应该使用的。哇,不敢相信我错过了解释的第二部分。谢谢。如果允许,我会在 8 分钟内将此问题标记为正确。
@sjagr>实际上,我之所以发表评论,是因为我将您对同一问题的回答链接到这里:stackoverflow.com/a/32897804/3212865。要点是问题混合了不同的通信层,最正交的响应实际上是 200,这意味着 “请求已成功处理并相应地进行了登录尝试,在响应的内容中查找结果”。试图在传输级状态码中表达应用级错误是一个设计错误。
我认为这个答案是错误的。附带的 WWW-Authenticate 的要求意味着 401 用于提示通过 HTTP Basic 或类似方式进行身份验证。对于失败的登录(在典型的基于 cookie 的登录场景中),您应该使用 403,如以下答案所述:webmasters.stackexchange.com/questions/24443/…
这似乎受到某些解释的影响,具体取决于某些陈述的字面意思。我的理解是该请求缺少有效的身份验证凭据,而不是根本没有凭据。由于第二部分仍然提到请求可能首先包含凭据,因此我认为 401 状态是正确的。
@sjagr我认为它根本没有凭据,因为标头中存在请求的凭据。发送 401 意味着您无权按照@spectras 的建议尝试登录。数据传输和应用程序逻辑之间存在关注点分离,因此为成功生成的失败登录响应发送 2xx 状态以外的任何内容都是不必要的、过于复杂,并且与您的 Web 服务器可能执行的其他操作不一致。
K
KernelDeimos

对于使用错误密码成功处理的登录请求,请使用 2xx 中的相应状态代码。

在问“什么是正确的 HTTP 状态码”之前,重要的是要考虑这个问题:“登录的成功或失败应该反映在响应的 HTTP 状态码中吗?”

在@sjagr 的回答中,突出显示了本节的第一部分。我将重点介绍第二部分并解释原因:

如果请求包含身份验证凭据,则 401 响应表明这些凭据的授权已被拒绝。用户代理可以使用新的或替换的授权头字段重复请求(第 4.2 节)。

这指的是 Authorization 标头,而不是包含登录凭据的请求正文。不幸的是,第一部分的措辞可能被误解为引用包含登录信息的请求正文。这种歧义可以通过考虑关注点分离来解决; (https://en.wikipedia.org/wiki/Separation_of_concerns) 服务器的响应头不应该依赖于两个有效请求体的差异,除非它导致内部服务器错误,否则数据传输和应用程序登录的问题开始相互渗透。

我将 HTTP 响应 2xx 用于有效的登录请求,其中客户端有权尝试登录,该请求已成功处理,响应指示成功或失败。

我也喜欢@spectras 在评论中表达这一点的方式:

试图在传输级状态码中表达应用级错误是一个设计错误。


I
ICW

如果您尝试使用错误密码登录 Google 帐户,它将返回 200 响应,其中包含指示密码不正确的数据。因此,我只使用 200。

归根结底,您使用哪个状态码纯粹是一个语义问题,不会改变您的应用程序的功能。真正重要的是您的应用程序向用户显示正确的信息。


从技术上讲是正确的答案,但只是“谷歌就是这样做的”并不是做某事的好理由
@Jake 考虑到以一种或另一种方式做这件事没有任何优势,这是一个足够好的理由。这是您只需要确保了解服务器将如何响应并做出相应反应的事情之一。无论您是否通过检查状态代码来做到这一点,对于应用程序的运行方式绝对没有影响,也不会使应用程序更易于维护。所以,真的,用这个做你想做的事。谷歌这样做的事实只是让人放心,这是一个可行的解决方案。有时可以说“没关系”