此处发布了一个类似的问题: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 看起来也不正确,因为数据被成功接受并且没有被拒绝。
话虽如此,应该使用的真正正确的响应是什么?
如果您严格使用 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 响应转发回登录页面上有意义的格式。
对于使用错误密码成功处理的登录请求,请使用 2xx
中的相应状态代码。
在问“什么是正确的 HTTP 状态码”之前,重要的是要考虑这个问题:“登录的成功或失败应该反映在响应的 HTTP 状态码中吗?”
在@sjagr 的回答中,突出显示了本节的第一部分。我将重点介绍第二部分并解释原因:
如果请求包含身份验证凭据,则 401 响应表明这些凭据的授权已被拒绝。用户代理可以使用新的或替换的授权头字段重复请求(第 4.2 节)。
这指的是 Authorization
标头,而不是包含登录凭据的请求正文。不幸的是,第一部分的措辞可能被误解为引用包含登录信息的请求正文。这种歧义可以通过考虑关注点分离来解决; (https://en.wikipedia.org/wiki/Separation_of_concerns) 服务器的响应头不应该依赖于两个有效请求体的差异,除非它导致内部服务器错误,否则数据传输和应用程序登录的问题开始相互渗透。
我将 HTTP 响应 2xx
用于有效的登录请求,其中客户端有权尝试登录,该请求已成功处理,响应指示成功或失败。
我也喜欢@spectras 在评论中表达这一点的方式:
试图在传输级状态码中表达应用级错误是一个设计错误。
如果您尝试使用错误密码登录 Google 帐户,它将返回 200 响应,其中包含指示密码不正确的数据。因此,我只使用 200。
归根结底,您使用哪个状态码纯粹是一个语义问题,不会改变您的应用程序的功能。真正重要的是您的应用程序向用户显示正确的信息。
WWW-Authenticate
的要求意味着 401 用于提示通过 HTTP Basic 或类似方式进行身份验证。对于失败的登录(在典型的基于 cookie 的登录场景中),您应该使用 403,如以下答案所述:webmasters.stackexchange.com/questions/24443/…2xx
状态以外的任何内容都是不必要的、过于复杂,并且与您的 Web 服务器可能执行的其他操作不一致。