3291

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

401 Unauthorized?
403 Forbidden?
还有什么?

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

4

19 回答 19

4758

Daniel Irvine的明确解释:

401 Unauthorized存在问题,这是身份验证错误的 HTTP 状态代码。仅此而已:它用于身份验证,而不是授权。接收到 401 响应是服务器告诉您,“您未通过身份验证 - 根本未通过身份验证或身份验证不正确 - 但请重新进行身份验证并重试。” 为了帮助您,它将始终包含一个WWW-Authenticate标头,用于描述如何进行身份验证。

这通常是由您的 Web 服务器返回的响应,而不是您的 Web 应用程序。

这也是非常暂时的;服务器要求您再试一次。

因此,对于授权,我使用403 Forbidden响应。它是永久性的,它与我的应用程序逻辑相关,而且它是比 401 更具体的响应。

收到 403 响应是服务器告诉你,“对不起。我知道你是谁——我相信你所说的你是谁——但你只是没有访问此资源的权限。也许如果您很好地询问系统管理员,您将获得许可。但请不要再打扰我,直到你的困境改变为止。”</p>

总之,401 Unauthorized响应应该用于缺少或错误的身份验证,而403 Forbidden响应应该在之后使用,当用户通过身份验证但无权对给定资源执行请求的操作时。

应该如何使用 http 状态代码的另一种很好的图片格式。

于 2011-08-04T06:24:41.817 回答
477

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

401 未经授权:

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

403 禁止:

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

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


于 2010-07-21T07:28:08.790 回答
325

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

简明扼要

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

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

详细而深入

来自 RFC2616

10.4.2 401 未经授权

该请求需要用户身份验证。响应必须包含一个 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

于 2013-02-05T17:14:37.073 回答
183
  +------------------------
  | 资源存在吗?(如果是私有的,通常在验证检查后检查)
  +------------------------
    | |
 否 | v 是
    v +------------------------
   404 | 是否已登录?(经过身份验证,又名用户会话)
   或 +------------------------
   401 | |
   403 否 | | 是的
   3xx vv
              401 +------------------------
       (404不透露)| 可以访问资源吗?(许可,授权,...)
              或 +------------------------
             重定向 | |
             登录 否 | | 是的
                               | |
                               vv
                               403 OK 200,重定向,...
                      (或 404:不显示)
                      (或 404:如果私有资源不存在)
                      (或 3xx:重定向)

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

  • 404 如果资源是公共的并且不存在或3xx 重定向
  • 除此以外:
  • 如果未登录或会话过期,则为 401
  • 如果用户无权访问资源(文件、json、...),则为 403
  • 404 如果资源不存在或不愿意透露任何东西,或者3xx 重定向

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

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

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

正如@ChrisH 所提到的,有一些重定向 3xx的选项(301、302、303、307 或根本不重定向并使用 401):

于 2015-02-23T11:00:51.947 回答
119

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

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

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

于 2010-07-21T07:26:43.333 回答
54

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

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

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

关于 401,这是来自RFC 7235(超文本传输​​协议(HTTP/1.1):身份验证)

3.1。401未经授权

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

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

10.4.4 403 禁止

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

2014 年RFC 7231(超文本传输​​协议(HTTP/1.1):语义和内容)改变了 403 的含义:

6.5.3. 403 禁止

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

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

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

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

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

于 2013-02-27T09:44:36.507 回答
48
  • 401 Unauthorized : 我不知道你是谁。这是一个身份验证错误。
  • 403 Forbidden : 我知道你是谁,但你没有访问该资源的权限。这是一个授权错误。
于 2019-08-06T12:37:12.923 回答
31

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

OWASP 有更多关于攻击者如何使用此类信息作为攻击的一部分的信息。

于 2014-12-25T09:09:45.023 回答
22

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

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

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

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

6.5.3. 403 禁止

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

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

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

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

于 2014-05-22T10:54:48.053 回答
16

这些是含义:

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

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

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

于 2019-11-19T10:17:39.850 回答
15

!!!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(未找到)代替

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

于 2015-02-25T09:03:49.470 回答
11

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

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

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

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

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

“请求需要用户认证。”

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

于 2012-10-01T14:34:32.210 回答
9

用英语:

401

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

403

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

于 2020-04-08T14:23:12.937 回答
7

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

在此处输入图像描述

于 2021-11-11T12:19:24.247 回答
5

这在我的脑海中比这里的任何地方都简单,所以:

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

403:你看不到这一点,HTTP 基本身份验证也无济于事。

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

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

这将 403 保留为“您需要登录”。

换句话说,403 表示“此资源需要某种形式的身份验证,而不是 HTTP 基本身份验证”。

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

于 2017-09-23T12:33:37.190 回答
4

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

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

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

401:客户端应指定凭据。

  • 指定的凭据格式无效

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

  • 指定的凭据引用了一个不存在的用户

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

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

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

  • 指定的凭据过期

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

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

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

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

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

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

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

于 2018-06-02T23:34:20.363 回答
1

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

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

401未经授权

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

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

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

403 禁止

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

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

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

于 2018-06-05T15:26:58.400 回答
1

401响应意味着以下之一:

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

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

于 2022-02-17T11:16:29.550 回答
-7

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

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

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

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

于 2014-12-12T19:01:43.510 回答