ChatGPT解决这个技术问题 Extra ChatGPT

对于存在的网页,但用户没有足够的权限(他们没有登录或不属于正确的用户组),应该提供什么正确的 HTTP 响应?

401 Unauthorized?
403 Forbidden?
还有什么?

到目前为止,我所读到的关于两者之间的区别并不是很清楚。每个响应适合哪些用例?

401 'Unauthorized' 应该是 401 'Unauthenticated',问题解决了!
我不记得我和我的同事有多少次因为这个问题回到 stackoverflow。也许 HTTP 标准应该考虑修改 401 和 403 的名称或描述。
@Qwerty 不,新的 RFC7231 淘汰了 RFC2616。 403 现在有了不同的含义。
@fishbone,您也没有注意到状态代码 401 已从该 RFC 中删除:D
@fishbone 现在它已被添加回该提案,但现在使用不同的 RFC 7235 tools.ietf.org/html/rfc7235#section-3.1

N
Nick T

Daniel Irvine [original link] 的明确解释:

401 Unauthorized 存在问题,这是身份验证错误的 HTTP 状态代码。仅此而已:它用于身份验证,而不是授权。接收到 401 响应是服务器告诉您,“您未通过身份验证 - 根本未通过身份验证或身份验证不正确 - 但请重新进行身份验证并重试。”为了帮助您,它将始终包含一个 WWW-Authenticate 标头,用于描述如何进行身份验证。这通常是由您的 Web 服务器返回的响应,而不是您的 Web 应用程序。这也是非常暂时的;服务器要求您再试一次。因此,对于授权,我使用 403 Forbidden 响应。它是永久性的,它与我的应用程序逻辑相关,并且它是比 401 更具体的响应。接收 403 响应是服务器告诉你,“对不起。我知道你是谁——我相信你所说的你是谁——但你只是没有访问此资源的权限。也许如果您很好地询问系统管理员,您将获得许可。不过在你的困境改变之前,请不要再打扰我了。”总之,401 Unauthorized 响应应该用于缺少或错误的身份验证,而 403 Forbidden 响应应该在之后使用,当用户通过身份验证但无权对给定资源执行请求的操作时。

应该如何使用 http 状态代码的另一个nice pictorial format


默认的 IIS 403 消息是“这是一个通用的 403 错误,意味着经过身份验证的用户无权查看该页面”,这似乎是同意的。
@JPReddy您的答案是正确的。但是,我希望将 401 命名为“未验证”,将 403 命名为“未授权”。与身份验证有关的 401 具有伴随文本“未经授权”的格式,这非常令人困惑......除非我的英语不好(这很有可能)。
@ZaidMasud,根据 RFC,这种解释是不正确的。 Cumbayah 的回答是正确的。 401 表示“您缺少正确的授权”。它意味着“如果你愿意,你可以尝试验证自己”。因此,未正确验证自己的客户端和未正确验证的客户端都将获得 401。403 表示“无论你是谁,我都不会回答这个问题”。 RFC 明确指出,在 403 的情况下“授权将无济于事”。
401是认证错误,403是授权错误。就那么简单。
对于所有引用 RFC(很可能是 2616)的反对者,你们都错了。正如@Idrut 在 answer 中指定的,“禁止意味着客户端已成功验证,但未授权。”。他引用了 RFC7231 和 RFC7235,它们 过时 RFC 2616。
C
Community

编辑:RFC2616 已过时,请参阅 RFC7231RFC7235

401 未经授权:

如果请求已包含授权凭证,则 401 响应表示已拒绝对这些凭证的授权。

403 禁止:

服务器理解请求,但拒绝执行。

从您的用例来看,用户似乎没有经过身份验证。我会返回401。


谢谢,这有助于我澄清它。我正在使用两者 - 401 用于未经身份验证的用户,403 用于权限不足的经过身份验证的用户。
我没有投反对票,但我发现这个答案非常具有误导性。 403 禁止更适合用于永远不会提供的内容(如 asp.net 中的 .config 文件)。它要么是那个,要么是 404。恕我直言,对于可以访问但您没有正确凭据的东西返回 403 是不合适的。我的解决方案是通过更改凭据的方式提供拒绝访问消息。那个或401。
“响应必须包含一个 WWW-Authenticate 标头字段(第 14.47 节),其中包含适用于所请求资源的质询。”如果您不想使用 HTTP 样式的身份验证,401 响应代码似乎是不合适的。
我会在这里支持比利安德。该语句是“如果请求已包含授权凭据”。这意味着如果这是来自提供凭证的请求的响应(例如来自 RFC2617 身份验证尝试的响应)。它本质上是允许服务器说,“错误的帐户/密码对,再试一次”。在提出的问题中,用户可能已通过身份验证但未授权。对于这些情况,401 绝不是适当的响应。
Billiand 是对的,401 仅适用于 HTTP 身份验证。
C
Community

缺少其他答案的是,必须理解 RFC 2616 上下文中的身份验证和授权仅指 RFC 2617 的 HTTP 身份验证协议。HTTP 状态代码不支持通过 RFC2617 之外的方案进行身份验证,因此不予考虑在决定是使用 401 还是 403 时。

简明扼要

Unauthorized 表示客户端未通过 RFC2617 身份验证,服务器正在启动身份验证过程。 Forbidden 表示客户端已通过 RFC2617 身份验证并且没有授权,或者服务器不支持请求资源的 RFC2617。

这意味着如果您有自己的滚动登录过程并且从不使用 HTTP 身份验证,则 403 始终是正确的响应,并且永远不应使用 401。

详细而深入

来自 RFC2616

10.4.2 401 Unauthorized 请求需要用户认证。响应必须包含一个 WWW-Authenticate 头字段(第 14.47 节),其中包含适用于所请求资源的质询。客户端可以使用合适的授权头域重复请求(第 14.8 节)。

10.4.4 403 Forbidden 服务器理解请求但拒绝执行。授权将无济于事,并且不应重复请求。

首先要记住的是,本文档上下文中的“身份验证”和“授权”专门指 RFC 2617 中的 HTTP 身份验证协议。它们不指您可能创建的任何滚动您自己的身份验证协议使用登录页面等。我将使用“登录”来指代通过 RFC2617 以外的方法进行的身份验证和授权

因此,真正的区别不在于问题是什么,也不在于是否有解决方案。不同之处在于服务器期望客户端下一步做什么。

401 表示无法提供资源,但服务器正在请求客户端通过 HTTP 身份验证登录并已发送响应头以启动该过程。可能存在允许访问资源的授权,也可能没有,但让我们试一试,看看会发生什么。

403表示无法提供资源,对于当前用户来说,无法通过RFC2617解决这个问题,也没有尝试的意义。这可能是因为已知没有足够的身份验证级别(例如因为 IP 黑名单),但也可能是因为用户已经通过身份验证并且没有权限。 RFC2617 模型是一个用户、一个凭据,因此可以忽略用户可能拥有第二组可以授权的凭据的情况。它既不暗示也不暗示某种登录页面或其他非 RFC2617 身份验证协议可能有帮助,也可能没有帮助——这超出了 RFC2616 标准和定义。

编辑:RFC2616 已过时,请参阅 RFC7231RFC7235


那么当用户请求一个需要非http认证的页面时,我们应该怎么做呢?发送状态码 403?
这很重要:“如果您有自己的滚动登录过程并且从不使用 HTTP 身份验证,那么 403 始终是正确的响应,并且永远不应该使用 401。”
@marcovtwout 发送 302 到您的登录页面,或发送 403 包含包含如何登录信息的正文?
RFC2616 应该被 RFC7235 烧毁和替换,但据我所知,该主题没有任何变化。
RFC7235 不提供“自己动手”或替代身份验证挑战吗?为什么我的应用程序的登录流程不能以 WWW-Authenticate 标头的形式提出挑战?即使浏览器不支持它,我的 React 应用程序也可以...
C
Christophe Roussy
+-----------------------
  | RESOURCE EXISTS ? (if private it is often checked AFTER auth check)
  +-----------------------
    |       |
 NO |       v YES
    v      +-----------------------
   404     | IS LOGGED-IN ? (authenticated, aka user session)
   or      +-----------------------
   401        |              |
   403     NO |              | YES
   3xx        v              v
              401            +-----------------------
       (404 no reveal)       | CAN ACCESS RESOURCE ? (permission, authorized, ...)
              or             +-----------------------
             redirect          |            |
             to login       NO |            | YES
                               |            |
                               v            v
                               403          OK 200, redirect, ...
                      (or 404: no reveal)
                      (or 404: resource does not exist if private)
                      (or 3xx: redirection)

检查通常按以下顺序进行:

404 如果资源是公共的并且不存在或 3xx 重定向

否则:

如果未登录或会话过期,则为 401

如果用户无权访问资源(文件、json、...),则为 403

404 如果资源不存在或不愿意透露任何东西,或者 3xx 重定向

UNAUTHORIZED:状态码(401)表示请求需要认证,通常这意味着用户需要登录(会话)。服务器未知的用户/代理。可以使用其他凭据重复。注意:这是令人困惑的,因为这应该被命名为“未经身份验证”而不是“未经授权”。如果会话过期,这也可能在登录后发生。特殊情况:可以用来代替 404 以避免暴露资源的存在或不存在(信用@gingerCodeNinja)

FORBIDDEN:状态码 (403) 表示服务器理解请求但拒绝执行。服务器已知但凭据不足的用户/代理。除非凭据更改,否则重复请求将不起作用,这在短时间内不太可能发生。特殊情况:可以使用而不是 404 来避免泄露资源的存在或不存在(信用@gingerCodeNinja),以防泄露资源的存在会暴露敏感数据或给攻击者提供有用的信息。

NOT FOUND:状态码 (404) 表示请求的资源不可用。用户/代理已知但服务器不会透露有关资源的任何信息,就好像它不存在一样。重复将不起作用。这是 404 的特殊用途(例如 github 就是这样做的)。

正如@ChrisH 所述,redirection 3xx 有几个选项(301、302、303、307 或根本不重定向并使用 401):

HTTP 重定向代码之间的区别

浏览器缓存 HTTP 301 多长时间?

重定向到登录页面时正确的 HTTP 状态代码是什么?

302 和 307 重定向有什么区别?


如果用户未登录或已登录但没有权限,并且内容不存在于该位置,有时您可能希望返回 401/403 而不是 404,这样您就不会暴露什么是或不是如果用户未经过身份验证和登录,则不存在。只要知道某些东西存在就可以暗示某些东西或破坏 NDA。因此,有时该图的 404 部分应移至已登录/已验证。
@gingerCodeNinja 是的,这与 404 而不是 403 的逻辑相同,很高兴提及这种情况。
感谢您提供所有级别的非常有效 no reveal 案例。当然,这在很大程度上取决于上下文,但我喜欢你已经明确表示在所有这些情况下它都是可能的一个选项。
@MattKocaj 请注意,有时可以通过细微的时间差异检测到 no reveal 案例,不应将其视为安全功能,它可能只会减慢攻击者的速度或对隐私有所帮助。
我认为您的意思是 302 而不是“301 重定向到登录”。
C
Cumbayah

根据 RFC 2616 (HTTP/1.1) 403 在以下情况下发送:

服务器理解请求,但拒绝执行。授权将无济于事,并且不应重复请求。如果请求方法不是 HEAD 并且服务器希望公开请求未完成的原因,它应该在实体中描述拒绝的原因。如果服务器不希望向客户端提供此信息,则可以使用状态码 404(未找到)代替

换句话说,如果客户端可以通过身份验证访问资源,则应该发送 401。


如果不清楚他们是否可以访问?假设我有 3 个用户级别 - Public、Members 和 Premium Members。假设该页面仅供高级会员使用。公共用户基本上是未经身份验证的,并且在登录时可能是会员或高级会员。对于会员用户级别,403 似乎合适。对于高级会员,401。但是,您为公众提供什么服务?
恕我直言,这是最准确的答案。这取决于应用程序,但通常,如果经过身份验证的用户对资源没有足够的权限,您可能希望提供一种更改凭据或发送 401 的方法。我认为 403 最适合从未提供过的内容。在 asp.net 中,这意味着 web.config 文件 *.resx 文件等,因为无论哪个用户登录,这些文件都将永远不会被提供,因此再试一次也没有意义。
+1,但不确定的+1。合乎逻辑的结论是永远不应该返回 403,因为 401 或 404 将是严格更好的响应。
@Mel我认为客户端不应访问的文件应该是404。它是系统内部的文件;外界甚至不应该知道它的存在。通过返回 403,您可以让客户端知道它的存在,无需将该信息泄露给黑客。 403 的规范说 An origin server that wishes to "hide" the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).
虽然在我看来这可能是对旧 RFC 2616 的准确解释,但请注意 RFC 7231 defines the semantics of a 403 differently,实际上明确指出 “客户端可以使用新的或不同的凭据重复请求。” 因此,虽然这个答案在 2010 年是准确的,但今天完全错误,因为状态码的含义已经在我们脚下被改写了。 (令人讨厌的是,Changes from RFC 2616 附录不承认更改!)
C
Community

假设 HTTP 身份验证(WWW-Authenticate 和 Authorization 标头)正在使用中,如果以另一个用户身份进行身份验证将授予对所请求资源的访问权限,则应返回 401 Unauthorized。

403 Forbidden 用于禁止所有人访问资源或限制在给定网络或仅允许通过 SSL 访问资源,只要它与 HTTP 身份验证无关。

如果未使用 HTTP 身份验证,并且服务具有基于 cookie 的身份验证方案(如现在的规范),则应返回 403 或 404。

关于 401,这是来自 RFC 7235 (Hypertext Transfer Protocol (HTTP/1.1): Authentication)

3.1。 401 Unauthorized 401 (Unauthorized) 状态码表示由于缺少目标资源的有效身份验证凭据,请求尚未应用。源服务器必须发送一个 WWW-Authenticate 头字段(第 4.4 节),其中包含至少一个适用于目标资源的质询。如果请求包含身份验证凭据,则 401 响应表明这些凭据的授权已被拒绝。客户端可以使用新的或替换的授权头字段重复请求(第 4.1 节)。如果 401 响应包含与先前响应相同的质询,并且用户代理已经尝试了至少一次身份验证,那么用户代理应该向用户呈现封闭的表示,因为它通常包含相关的诊断信息。

403(和 404)的语义随着时间而改变。这是从 1999 年开始的 (RFC 2616):

10.4.4 403 Forbidden 服务器理解请求,但拒绝执行。授权将无济于事,并且不应重复请求。如果请求方法不是 HEAD 并且服务器希望公开请求未完成的原因,它应该在实体中描述拒绝的原因。如果服务器不希望向客户端提供此信息,则可以使用状态代码 404(未找到)来代替。

2014 年 RFC 7231 (Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content) 改变了 403 的含义:

6.5.3. 403 Forbidden 403(Forbidden)状态码表示服务器理解请求但拒绝授权。希望公开请求被禁止的原因的服务器可以在响应负载(如果有)中描述该原因。如果请求中提供了身份验证凭据,则服务器认为它们不足以授予访问权限。客户端不应使用相同的凭据自动重复请求。客户端可以使用新的或不同的凭据重复请求。但是,由于与凭证无关的原因,可能会禁止请求。希望“隐藏”当前存在的被禁止目标资源的源服务器可以改为响应状态码 404(未找到)。

因此,403(或 404)现在可能意味着任何事情。提供新的凭据可能会有所帮助……也可能不会。

我相信这种情况发生变化的原因是 RFC 2616 假设在实践中使用 HTTP 身份验证时,今天的 Web 应用程序使用例如表单和 cookie 构建自定义身份验证方案。


这是有趣的。基于 RFC 7231 和 RFC 7235,我看不出 401 和 403 之间有明显区别
403 的意思是“我认识你,但你看不到这个资源”。没有理由混淆。
“如果请求包含身份验证凭据,则 401 响应表明这些凭据的授权已被拒绝。客户端可以使用新的或替换的授权头字段(第 4.1 节)重复请求。”但是,然后是“4.2. 'Authorization' 标头字段允许用户代理向原始服务器验证自己”。看起来在 RFC7235 中他们使用术语“授权”,就像它是“身份验证”一样。在这种情况下,经过身份验证但未授权的用户似乎不应该得到 401,而是 403
@Brian 主要区别是,如果您的系统使用 RFC 7235 中指定的 HTTP 身份验证,则返回 401(因此您必须返回带有此类响应的 WWW-Authenticate 标头),否则返回 403。
@MichaelBlackburn 不,事实并非如此。服务器不需要知道您返回 403。一方面,旧的 RFC 2616 规范和新的 RFC 7231 规范都没有这样说;另一方面,新规范中的“如果在请求中提供了身份验证凭据”这句话只有在请求中不包含身份验证凭据的某些情况下(即服务器确实确实如此的情况下)可以返回 403 时才有意义不是“认识你”)。
P
Premraj

401未经授权:我不知道你是谁。这是一个身份验证错误。

403 Forbidden:我知道你是谁,但你没有访问该资源的权限。这是一个授权错误。


不确定它特别“总是”意味着发件人是未知的。只是他们要求的任何东西都没有得到授权。
虽然您的解释看起来令人信服,但我不满意或不相信它,因为错误 401 表示名称本身的授权,而您正在与身份验证混合使用。好吧,我可以告诉一个场景,使用我获得令牌的凭据意味着成功通过身份验证,并使用它来访问该令牌的“未经授权的资源”。那是未经授权的401。你对此有什么要说的?
@Jasmine 您的担忧是可以理解的,但上述解释是正确的。术语冲突是由 http 规范不符合当前广泛使用的术语“身份验证”和“授权”定义引起的。可能是由于这些定义没有像现在这样普遍使用。我们被冲突及其引起的混乱所困扰。支持这一点的证据是浏览器的默认行为是在 401 响应中提示输入凭据。
这是对公认答案中描述的区别的精辟总结。但是,就像公认的答案一样,这完全是错误的。 HTTP 规范中没有任何内容支持这种区别,而且规范根本不允许使用返回 401 的 WWW-AuthenticateAuthorization 标头的典型网站登录系统。
P
Patrick White

这是一个较老的问题,但从未真正提出的一个选项是返回 404。从安全角度来看,投票最高的答案可能会受到 information leakage vulnerability 的影响。比如说,有问题的安全网页是系统管理页面,或者更常见的是,是系统中用户无权访问的记录。理想情况下,您甚至不希望恶意用户知道那里有页面/记录,更不用说他们无权访问了。当我构建这样的东西时,我会尝试在内部日志中记录未经身份验证/未经授权的请求,但返回 404。

OWASP 有一些关于攻击者如何将此类信息用作攻击的一部分的more information


之前的答案中已经提到了 404 的使用。您说得对:信息泄漏,这对于任何推出自己的身份验证/授权方案的人来说应该是一个重要的考虑因素。 +1 提及 OWASP。
具有讽刺意味的是,OWASP 链接现在转到 404 页面。我在 owasp.org/index.php/… 上发现了类似的东西(我认为)
取决于 API 以及如何授予访问权限。但是“泄漏”不是问题,如果它为用户名/密码返回 401,它肯定与 Web 表单相同吗?
@anned20 具有讽刺意味的是,您发布的链接也返回 404 页面。
C
Community

前段时间有人问过这个问题,但人们的想法还在继续。

此草稿(由 Fielding 和 Reschke 撰写)中的 Section 6.5.3 赋予状态代码 403 与 RFC 2616 中记录的含义略有不同的含义。

它反映了许多流行的 Web 服务器和框架所采用的身份验证和授权方案中发生的情况。

我已经强调了我认为最突出的一点。

6.5.3. 403 Forbidden 403(Forbidden)状态码表示服务器理解请求但拒绝授权。希望公开请求被禁止的原因的服务器可以在响应负载(如果有)中描述该原因。如果请求中提供了身份验证凭据,则服务器认为它们不足以授予访问权限。客户端不应使用相同的凭据重复请求。客户端可以使用新的或不同的凭据重复请求。但是,由于与凭证无关的原因,可能会禁止请求。希望“隐藏”当前存在的被禁止目标资源的源服务器可以改为响应状态码 404(未找到)。

无论您使用什么约定,重要的是在您的站点/API 中提供统一性。


该草案获得批准,现在是 RFC 7231。
L
Luca C.

这些是含义:

401:用户未(正确)认证,资源/页面需要认证

403:用户的角色或权限不允许访问请求的资源,例如用户不是管理员,请求的页面是管理员的。

注意:从技术上讲,403 是 401 的超集,因为为未经身份验证的用户提供 403 也是合法的。反正区分更有意义。


这是对这个问题的一个很好的 TLDR 答案。
这写得很清楚,直截了当,但是错了。当用户未通过身份验证时,返回 403s 是完全可以的。规范中没有其他说明,并且通常在这种情况下您不能使用 401,因为只有在包含 WWW-Authenticate 标头时返回 401 才是合法的。
tx @MarkAmery,我稍微更正了句子以包括可能的认证
L
Levite

!!! DEPR:答案反映了 2014 年之前的常见做法!!!

TL;博士

401:与身份验证有关的拒绝

403:与身份验证无关的拒绝

实际例子

如果 apache 需要身份验证(通过 .htaccess),并且您点击 Cancel,它将以 401 Authorization Required 响应

如果 nginx 找到一个文件,但没有 访问权限(用户/组)来读取/访问它,它将以 403 Forbidden 响应

RFC(2616 第 10 节)

401 未经授权 (10.4.2)

含义1:需要认证

该请求需要用户身份验证。 ...

含义2:身份验证不足

...如果请求已包含授权凭据,则 401 响应表明已拒绝对这些凭据的授权。 ...

403禁止(10.4.4)

含义:与身份验证无关

...授权无济于事...

更多细节:

服务器理解请求,但拒绝执行。

它应该描述实体中拒绝的原因

可以使用状态码 404(未找到)代替

(如果服务器想从客户端保留此信息)


您的“授权将无济于事”引用自 2014 年 6 月以来已过时的规范。tools.ietf.org/html/rfc7231 替换它并说相反 - “客户可以使用新的或不同的凭据重复请求。” 因此,现在绝对可以在“需要验证”和“验证不足”的场景中使用 403 响应。
谢谢!如果你愿意,你可以编辑答案。现在我在顶部放了一个弃用警告。
Z
Zaid Masud

他们没有登录或不属于正确的用户组

您已经陈述了两种不同的情况;每种情况都应该有不同的反应:

如果他们根本没有登录,你应该返回 401 Unauthorized 如果他们已经登录但不属于正确的用户组,你应该返回 403 Forbidden

根据收到的对此答案的评论,请注意 RFC:

如果用户未登录,则他们是未经身份验证的,其 HTTP 等价物是 401,并且在 RFC 中被误导性地称为未经授权。正如 401 Unauthorizedsection 10.4.2 所述:

“该请求需要用户身份验证。”

如果您未经身份验证,则 401 是正确的响应。但是,如果您未经授权,在语义上正确的意义上,403 是正确的响应。


这是不正确的。请参阅 RFC 和 @Cumbayah 的回答。
@DavideR。 RFC 交替使用身份验证和授权。我相信当阅读认证含义时它更有意义。
这个答案是反过来的。未经授权与未经身份验证不同。 @DavideR 是对的。身份验证和授权不可互换
2616应该被烧掉。一些较新的 RFC 更清楚地表明,需要区分“我不认识你”和“我认识你,但你不能访问它”。没有正当理由承认存在永远不会实现(或不通过 http 实现)的资源,这就是 403-truthers 所建议的。
P
Pratham

我为您创建了一个简单的注释,它会说明清楚。

https://i.stack.imgur.com/w9ZsZ.png


J
James

用英语讲:

401

您可能被允许访问,但出于某种原因,您被拒绝了此请求。比如密码错误?再试一次,如果请求正确,您将获得成功响应。

403

你永远不被允许。你的名字不在名单上,你永远不会进入,离开,不要发送重试请求,它会被拒绝,永远。离开。


只是不正确。 current spec's description of 403 声明 “客户端可以使用新的或不同的凭据重复请求。”,这与您在此处对 403 的描述相矛盾。
@MarkAmery“使用新的或不同的凭据重复”好的,所以我的答案仍然有效,因为新的或不同的请求不是“重试”是吗?如果您以自己的用户身份登录并获得 403,然后再试一次,您将获得 403。如果您以 Admin 用户注销并重新登录,现在却获得 200,这不是重试请求。这是一个完全不同的请求,具有不同的凭据。所以我的回答仍然成立,“你”是不允许的,“你的”名字不在名单上,“你”永远不会进入,“不要发送重试请求”。使用不同的凭据不是“重试”,而是新请求。
V
Vladimir Kornea

401:您需要 HTTP 基本身份验证才能看到这一点。

如果用户只需要使用您站点的标准 HTML 登录表单登录,则 401 将不合适,因为它特定于 HTTP 基本身份验证。

403:此资源存在,但您无权查看,HTTP 基本身份验证无济于事。

我不建议使用 403 来拒绝对 /includes 之类的访问,因为就网络而言,这些资源根本不存在,因此应该使用 404。

换句话说,403 表示“此资源需要某种形式的身份验证,而不是 HTTP 基本身份验证(例如使用网站的标准 HTML 登录表单)”。

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2


G
Grant Gryczan

我认为重要的是要考虑到,对于浏览器,401 会为用户启动一个身份验证对话框以输入新的凭据,而 403 则不会。浏览器认为,如果返回 401,则用户应该重新进行身份验证。所以 401 代表无效的身份验证,而 403 代表没有权限。

以下是该逻辑下的一些情况,其中会从身份验证或授权中返回错误,其中重要的短语以粗体显示。

资源需要身份验证,但未指定凭据。

401:客户端应指定凭据。

指定的凭据格式无效。

400:既不是 401 也不是 403,因为语法错误应该总是返回 400。

指定的凭据引用了不存在的用户。

401:客户端应指定有效凭据。

指定的凭据无效,但指定了有效用户(如果不需要指定用户,则不指定用户)。

401:同样,客户端应该指定有效的凭据。

指定的凭据已过期。

401:这实际上与通常具有无效凭据相同,因此客户端应指定有效凭据。

指定的凭证是完全有效的,但不足以满足特定资源的要求,尽管具有更多权限的凭证可能可以。

403:指定有效凭证不会授予对资源的访问权限,因为当前凭证已经有效但没有权限。

无论凭据如何,都无法访问特定资源。

403:这与凭据无关,因此指定有效凭据无济于事。

指定的凭据完全有效,但特定客户端被阻止使用它们。

403:如果客户端被阻止,指定新的凭据不会做任何事情。


C
Community

鉴于有关此事的最新 RFC(72317235),用例似乎很清楚(添加了斜体):

401 表示未经身份验证(“缺少有效身份验证”);即“我不知道你是谁,或者我不相信你就是你所说的那个人。”

401未经授权

401(未授权)状态码表示该请求尚未应用,因为它缺少目标资源的有效身份验证凭据。生成 401 响应的服务器必须发送一个 WWW-Authenticate 头字段(第 4.1 节),其中包含至少一个适用于目标资源的质询。

如果请求包含身份验证凭据,则 401 响应表明这些凭据的授权已被拒绝。用户代理可以使用新的或替换的授权头字段重复请求(第 4.2 节)。如果 401 响应包含与先前响应相同的质询,并且用户代理已经尝试了至少一次身份验证,那么用户代理应该向用户呈现封闭的表示,因为它通常包含相关的诊断信息。

403 表示未授权(“拒绝授权”);即“我知道你是谁,但你没有访问此资源的权限。”

403 禁止

403(Forbidden)状态码表示服务器理解请求但拒绝授权。希望公开请求被禁止的原因的服务器可以在响应负载(如果有)中描述该原因。

如果请求中提供了身份验证凭据,则服务器认为它们不足以授予访问权限。客户端不应使用相同的凭据自动重复请求。客户端可以使用新的或不同的凭据重复请求。但是,由于与凭证无关的原因,可能会禁止请求。

希望“隐藏”当前存在的被禁止目标资源的源服务器可以改为响应状态码 404(未找到)。


-1;这些段落已在此处的其他答案中被引用,而您的则没有增加任何新内容。我认为显然不清楚区别是什么。您将这两个代码总结为“缺乏有效的身份验证”和“拒绝授权”,但我无法想象在任何情况下这些简短描述中的一个将适用,而另一个也无法解释为适用。
这里有很多答案,涵盖了许多 RFC,并且经过编辑和更新,混淆了水域。我提供了一个链接来解释 authenticated 是什么以及 authorized 是什么,并省略了所有过时的 RFC,以便清楚地了解应用程序。
您的编辑澄清了您对这两个代码的解释,这似乎与许多其他人的解释相匹配。但是,我个人认为这种解释意义不大。在 403 描述中使用短语“如果提供了身份验证凭据”意味着即使没有提供凭据,403 也可能是合适的——即“未经身份验证”的情况。同时,对我来说,对 401 描述中包含的短语“for the target resource”最自然的解释是,401 可以用于经过身份验证但未授权的用户。
R
Ran Turner

401 响应表示以下之一:

缺少访问令牌。访问令牌已过期、已撤销、格式错误或无效。

另一方面,403 响应意味着访问令牌确实有效,但用户没有适当的权限来执行请求的操作。


t
theMyth

我对它的看法与接受的答案略有不同。

身份验证失败时返回 403 和授权失败时返回 401 似乎更具语义和逻辑性。

这是我的理由:

当您请求进行身份验证时,您有权提出该请求。您需要,否则一开始就没有人能够通过身份验证。

如果您的身份验证失败,您将被禁止,这在语义上是有意义的。

另一方面,禁止也可以申请授权,但假设您已通过身份验证并且您无权访问特定端点。返回 401 Unauthorized 似乎更具语义性。

Spring Boot 的安全性为失败的身份验证尝试返回 403


S
Shawn

在 401 vs 403 的情况下,这个问题已经回答了很多次了。这本质上是一场“HTTP 请求环境”的辩论,而不是一场“应用程序”的辩论。

关于roll-your-own-login问题(应用程序)似乎有一个问题。

在这种情况下,仅仅没有登录不足以发送 401 或 403,除非您使用 HTTP Auth 与登录页面(与设置 HTTP Auth 无关)。听起来您可能正在寻找“201 Created”,其中存在滚动您自己的登录屏幕(而不是请求的资源),用于应用程序级别的文件访问。这说:

“我听说了,它在这里,但你可以试试这个(你不能看到它)”


究竟在创造什么?
该问题指出/询问“用户没有足够的权限”,我无法想到您的“201”除了完全错误并且让客户完全困惑之外的任何情况。特别是如果我的请求与“创建”无关,即如果我只想登录或获取一些我期望 200 的东西。