403 Forbidden vs 401 Unauthorized HTTP 响应

问:

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

401 Unauthorized? 403 Forbidden? 还有什么?

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

答1:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

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。

答2:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

编辑:RFC2616 已过时,请参阅 RFC7231 和 RFC7235。

401 未经授权:

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

403 禁止:

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

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

谢谢,这有助于我澄清它。我正在使用两者 - 401 用于未经身份验证的用户,403 用于权限不足的经过身份验证的用户。

我没有投反对票,但我发现这个答案非常具有误导性。 403 禁止更适合用于永远不会提供的内容(如 asp.net 中的 .config 文件)。它要么是那个,要么是 404。恕我直言,对于可以访问但您没有正确凭据的东西返回 403 是不合适的。我的解决方案是通过更改凭据的方式提供拒绝访问消息。那个或401。

“响应必须包含一个 WWW-Authenticate 标头字段(第 14.47 节),其中包含适用于所请求资源的质询。”如果您不想使用 HTTP 样式的身份验证,401 响应代码似乎是不合适的。

我会在这里支持比利安德。该语句是“如果请求已包含授权凭据”。这意味着如果这是来自提供凭证的请求的响应(例如来自 RFC2617 身份验证尝试的响应)。它本质上是允许服务器说,“错误的帐户/密码对,再试一次”。在提出的问题中,用户可能已通过身份验证但未授权。对于这些情况,401 绝不是适当的响应。

Billiand 是对的,401 仅适用于 HTTP 身份验证。

答3:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

缺少其他答案的是,必须理解 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 已过时,请参阅 RFC7231 和 RFC7235。

那么当用户请求一个需要非http认证的页面时,我们应该怎么做呢?发送状态码 403?

这很重要:“如果您有自己的滚动登录过程并且从不使用 HTTP 身份验证,那么 403 始终是正确的响应,并且永远不应该使用 401。”

@marcovtwout 发送 302 到您的登录页面,或发送 403 包含包含如何登录信息的正文?

RFC2616 应该被 RFC7235 烧毁和替换,但据我所知,该主题没有任何变化。

RFC7235 不提供“自己动手”或替代身份验证挑战吗?为什么我的应用程序的登录流程不能以 WWW-Authenticate 标头的形式提出挑战?即使浏览器不支持它,我的 React 应用程序也可以...

答4:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

+-----------------------
  | 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 重定向到登录”。

答5:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

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

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

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

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

如果不清楚他们是否可以访问?假设我有 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 附录不承认更改!)

答6:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

假设 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 时才有意义不是“认识你”)。

答7:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

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

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

不确定它特别“总是”意味着发件人是未知的。只是他们要求的任何东西都没有得到授权。

虽然您的解释看起来令人信服,但我不满意或不相信它,因为错误 401 表示名称本身的授权,而您正在与身份验证混合使用。好吧,我可以告诉一个场景,使用我获得令牌的凭据意味着成功通过身份验证,并使用它来访问该令牌的“未经授权的资源”。那是未经授权的401。你对此有什么要说的?

@Jasmine 您的担忧是可以理解的,但上述解释是正确的。术语冲突是由 http 规范不符合当前广泛使用的术语“身份验证”和“授权”定义引起的。可能是由于这些定义没有像现在这样普遍使用。我们被冲突及其引起的混乱所困扰。支持这一点的证据是浏览器的默认行为是在 401 响应中提示输入凭据。

这是对公认答案中描述的区别的精辟总结。但是,就像公认的答案一样,这完全是错误的。 HTTP 规范中没有任何内容支持这种区别,而且规范根本不允许不使用返回 401 的 WWW-Authenticate 和 Authorization 标头的典型网站登录系统。

答8:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

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

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

之前的答案中已经提到了 404 的使用。您说得对:信息泄漏,这对于任何推出自己的身份验证/授权方案的人来说应该是一个重要的考虑因素。 +1 提及 OWASP。

具有讽刺意味的是,OWASP 链接现在转到 404 页面。我在 owasp.org/index.php/… 上发现了类似的东西(我认为)

取决于 API 以及如何授予访问权限。但是“泄漏”不是问题,如果它为用户名/密码返回 401,它肯定与 Web 表单相同吗?

@anned20 具有讽刺意味的是,您发布的链接也返回 404 页面。

答9:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

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

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

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

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

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

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

该草案获得批准,现在是 RFC 7231。

答10:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

这些是含义:

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

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

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

这是对这个问题的一个很好的 TLDR 答案。

这写得很清楚,直截了当,但是错了。当用户未通过身份验证时,返回 403s 是完全可以的。规范中没有其他说明,并且通常在这种情况下您不能使用 401,因为只有在包含 WWW-Authenticate 标头时返回 401 才是合法的。

tx @MarkAmery,我稍微更正了句子以包括可能的认证

答11:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

!!! 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 响应。

谢谢!如果你愿意,你可以编辑答案。现在我在顶部放了一个弃用警告。

原文链接:https://www.huntsbot.com/qa/8KBX/403-forbidden-vs-401-unauthorized-http-responses?lang=zh_CN&from=csdn

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值