题 403 Forbidden vs 401 Unauthorized HTTP响应


对于存在的网页,但对于没有足够权限的用户(他们未登录或不属于正确的用户组),要提供的正确HTTP响应是什么? 401? 403?别的什么?到目前为止,我对每个人的看法都不太清楚。哪些用例适合每个响应?


1905
2017-07-21 07:21


起源


401'未经授权'应为401'未经身份验证',问题解决了! - Christophe Roussy
哇。以下答案在整个地图上都是荒谬的。对于非HTTP身份验证,似乎未定义正确的答案。 - Joe Lapp
我不记得我和我的同事有多少次回到stackoverflow这个问题了。也许HTTP标准应该考虑修改401和403的名称或描述。 - neurite
事实上,我得到了这个错误的不同版本。比如“os_authType是'any'并且发送了一个无效的cookie”。所以无法弄清楚如何解决这个问题。谷歌搜索了很多时间,得到了理由,但没有得到解决方案。 - Sandeep Anand
@Qwerty no,新的RFC7231废弃了RFC2616。 403现在具有不同的含义。 - fishbone


答案:


一个明确的解释 丹尼尔欧文

有一个问题 401未经授权,身份验证错误的HTTP状态代码。就是这样:它用于身份验证,而不是授权。   收到401响应是服务器告诉你,“你不是   经过身份验证 - 未经过身份验证或经过身份验证   不正确 - 但请重新认证并再试一次。“为了帮助你,   它总是包括一个 WWW身份验证 标题描述如何   进行身份验证。

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

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

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

收到403响应是服务器告诉你,“对不起。我知道   你是谁 - 我相信你说的是你 - 但你却没有   访问此资源的权限。也许你问问系统   管理员很好,你会获得许可。但请不要打扰   再次,直到你的困境发生变化。“

总之,一个 401未经授权 响应应该用于遗漏   或不良认证,和 403禁止 应该使用响应   之后,当用户通过身份验证但未获得授权时   对给定资源执行请求的操作。

另一个 漂亮的图案格式 如何使用http状态代码。


2844
2017-08-04 06:24



默认的IIS 403消息是“这是一般403错误,意味着经过身份验证的用户无权查看该页面”,这似乎是一致的。 - Ben Challenor
@JPReddy你的回答是对的。但是,我希望将401命名为“Unauthenticated”,并将403命名为“Unauthorized”。令人非常困惑的是,401与身份验证有关,其格式伴随着文本“未经授权”......除非我不擅长英语(这很有可能)。 - p.matsinopoulos
@ZaidMasud,根据RFC的解释是不正确的。 Cumbayah的回答是正确的。 401表示“您错过了正确的授权”。它意味着“如果你想要你可能会尝试认证自己”。因此,未正确验证自身的客户端和未通过授权的经过适当验证的客户端都将获得401. 403意味着“我不会回答这个问题,无论您是谁”。 RFC明确指出,在403的情况下,“授权将无济于事”。 - Davide R.
401是认证错误,403是授权错误。就那么简单。 - Shahriyar Imanov
你遗漏了“嗯,这是我对它的看法:)”从他的博客文章复制时,不幸的是他的观点是错误的。正如其他人所说,403意味着无论您被认证为谁,都无法访问资源。我通常将此状态代码用于由我不希望直接访问的IP地址范围或我的webroot中的文件锁定的资源(即脚本必须为它们提供服务)。 - Kyle


看到 RFC2616

401未经授权:

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

403禁止:

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

更新

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


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


336
2017-07-21 07:28



谢谢,这有助于我澄清它。我正在使用两者 - 未经身份验证的用户使用401,权限不足的经过身份验证的用户使用403。 - VirtuosiMedia
我没有投票,但我觉得这个答案很容易让人误解。 403 forbidden更适用于永远不会被提供的内容(如asp.net中的.config文件)。无论是那个还是404. imho,为了可以访问的东西返回403是不合适的,但是你没有正确的凭据。我的解决方案是提供一个访问被拒绝的消息,其中包含一种更改凭据的方法。那个或401。 - Mel
“响应必须包含一个WWW-Authenticate头字段(第14.47节),其中包含适用于所请求资源的质询。”看起来如果您不想使用HTTP样式的身份验证,401响应代码是不合适的。 - Brilliand
我会在这里支持Billiand。声明是“如果请求已包含授权凭证”。这意味着如果这是来自提供凭证的请求的响应(例如来自RFC2617认证尝试的响应)。它本质上是允许服务器说“错误的帐户/密码对,再试一次”。在提出的问题中,用户可能是经过身份验证但未经授权。对于那些情况,401永远不是适当的回应。 - ldrut
Brilliand是对的,401仅适用于HTTP身份验证。 - Juampi


缺少其他答案的一点是,必须理解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节),其中包含适用于所请求资源的质询。客户端可以使用合适的Authorization头字段重复请求(第14.8节)。

10.4.4 403禁止   服务器理解请求,但拒绝履行请求。授权无效,请求不应重复。

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

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

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

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


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


254
2018-02-05 17:14



恕我直言,这是迄今为止最好,最准确的答案。 - Juampi
那么当用户请求需要非http身份验证的页面时,我们应该怎么做?发送状态代码403? - marcovtwout
这是回答我对这种区别的问题的答案。 - Patrick
这很重要:“如果你有自己的滚动自己的登录过程并且从不使用HTTP身份验证,则403始终是正确的响应,并且永远不应该使用401。” - ggg
RFC7235不提供“自己动手”或备用auth挑战吗?为什么我的应用程序的登录流程无法以a的形式呈现其挑战 WWW-Authenticate 头?即使浏览器不支持它,我的React应用程序也可以...... - jchook


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

服务器理解请求,但拒绝履行请求。授权无效,请求不应重复。如果请求方法不是HEAD并且服务器希望公开为什么请求没有得到满足,那么它应该描述实体中拒绝的原因。如果服务器不希望将此信息提供给客户端,则可以使用状态代码404(未找到)

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


95
2017-07-21 07:26



如果不清楚他们是否可以访问?假设我有3个用户级别 - 公共,成员和高级会员。假设该页面仅适用于高级会员。公共用户基本上是未经身份验证的 可以 在登录时可以是会员或高级会员。对于会员用户级别,403似乎是合适的。对于高级会员,401。但是,您为公众服务的是什么? - VirtuosiMedia
imho,这是最准确的答案。它取决于应用程序,但通常,如果经过身份验证的用户对资源没有足够的权限,您可能希望提供更改凭据或发送401的方法。我认为403最适合从未提供的内容。在asp.net中,这将意味着web.config文件* .resx文件等,因为无论哪个用户登录,这些文件都不会被提供,因此没有必要再次尝试。 - Mel
这个答案值得更多的赞成。我同意@Mel。 - Camilo Martin
+1,但不确定+1。逻辑结论是永远不应该返回403,因为401或404将是严格更好的响应。 - CurtainDog
@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). - Juan Mendes


TL; DR版本

    GET资源,存在吗?
    | |
    | |
    v v
NO:404是:经过身份验证吗?
             | |
             | |
             v v
           NO:401 YES:可以访问资源吗?
           (或:404)| |
           或301 | |
           重定向v v
           登录NO:403 OK 200,301,...

支票通常按以下顺序进行:

  • 401如果没有登录或会话已过期
  • 403如果用户没有访问资源的权限
  • 404如果资源不存在

未经授权:状态代码(401),指示请求需要 认证。用户/代理未知的服务器。可以重复其他凭据。注意:这很令人困惑,因为它应该被命名为“未经身份验证”而不是“未经授权”。

FORBIDDEN:状态代码(403),指示服务器理解请求但拒绝履行请求。服务器已知的用户/代理但具有 证书不足。重复请求将不起作用。

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


46
2018-02-23 11:00



github.com/for-GET/http-decision-diagram - Christophe Roussy
例如,我已登录,我可以访问一个页面,但它没有为我启用权限。哪些状态代码会返回? - barteloma
@bookmarker Loggin in称为身份验证,这是第一步。因此,如果您在登录后没有权限,则会获得403 Forbidden(凭据不足意味着您没有足够的权限)。 - Christophe Roussy
清楚,简单的解释。正是我需要的。 - Estevez


如果作为另一个用户进行身份验证将授予对所请求资源的访问权限,则应返回401 Unauthorized。 403 Forbidden主要用于禁止向所有人访问资源或仅限于给定网络或只允许通过SSL访问资源,只要它与身份验证无关。

来自RFC 7235(超文本传输​​协议(HTTP / 1.1):身份验证):

3.1。 401未经授权

401(未授权)状态代码表示请求具有   未应用,因为它缺少有效的身份验证凭据   对于目标资源。原始服务器必须发送一个   WWW-Authenticate头字段(第4.4节)至少包含一个   适用于目标资源的挑战。 如果请求   包括身份验证凭据,然后是401响应   表示已拒绝授权   证书。客户端可以用新的或者重复请求   替换了Authorization标头字段(第4.1节)。如果是401   响应包含与先前响应相同的挑战,以及   用户代理已经尝试过至少一次身份验证   用户代理应该给出包含的表示   用户,因为它通常包含相关的诊断信息。

这是来自RFC 2616:

10.4.4 403禁止

服务器理解请求,但拒绝履行请求。
授权无济于事 并且请求不应重复。
  如果请求方法不是HEAD并且服务器希望进行
  公开为什么请求没有得到满足,它应该描述   实体拒绝的原因。如果服务器不希望   将此信息提供给客户端,状态代码404
  可以使用(未​​找到)。

编辑:RFC 7231(超文本传输​​协议(HTTP / 1.1):语义和内容)更改403的含义:

6.5.3。 403禁止

403(禁止)状态代码表示服务器   了解该请求但拒绝授权。一个服务器   希望公开为什么禁止请求可以   在响应有效负载中描述该原因(如果有的话)。

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

希望“隐藏”当前存在的原始服务器
  禁止目标资源可以使用状态代码来响应
  404(未找到)。

因此,403现在可能意味着什么。提供新凭据可能会有所帮助......或者可能没有。


37
2018-02-27 09:44



这很有趣。基于RFC 7231和RFC 7235,我没有看到401和403之间的明显区别 - Brian
403表示“我认识你,但你看不到这个资源。”没有理由混淆。 - Michael Blackburn
“如果请求包含身份验证凭据,则401响应表示已拒绝授权这些凭据。客户端可以使用新的或替换的授权头字段重复请求(第4.1节)。”但是,然后“4.2。'授权'标题字段允许用户代理使用原始服务器对自身进行身份验证”。在RFC7235中看起来他们使用术语“授权”,就像它是“身份验证”。在这种情况下,似乎经过身份验证但未经授权的用户不应该获得401,而是403 - arcuri82


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

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


20
2017-12-25 09:09



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


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

第6.5.3节 在该草案中(由Fielding和Reschke撰写)给出了状态代码403与文档中记载的含义略有不同的含义 RFC 2616

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

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

6.5.3。 403禁止

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

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

希望“隐藏”当前存在的禁止目标资源的原始服务器可以用状态代码404(未找到)进行响应。

无论您使用哪种惯例,重要的是在您的网站/ API中提供一致性。


19
2018-05-22 10:54



草案获得批准,现在是RFC 7231。 - Vebjorn Ljosa


TL; DR

  • 401:拒绝与身份验证有关
  • 403:与认证无关的拒绝

实际例子

如果 阿帕奇  要求认证 (通过 .htaccess),你打了 Cancel,它会回应一个 401 Authorization Required

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

RFC(2616第10节)

401未经授权(10.4.2)

含义1: 需要验证

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

意思2: 认证不足

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

403禁止(10.4.4)

含义: 与身份验证无关

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

更多细节:

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

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

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

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


9
2018-02-25 09:03





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

你说过两种不同的情况;每个案例应该有不同的回应:

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

7
2017-10-01 14:34



这是不正确的。参考 RFC 和@ Cumbayah的回答。 - Davide R.
@DavideR。 RFC使用 认证 和 授权 互换。我相信在阅读时更有意义 认证 含义。 - Zaid Masud
这个答案是相反的。未授权与未经身份验证的不同。 @DavideR是对的。身份验证和授权不可互换 - BozoJoe
@BozoJoe我们都同意未经授权和未经认证的区别。如果用户未登录,则他们未经过身份验证,其HTTP等效值为401,误导性地称为“未授权”。如果你看第10.4.2节 这里 它声明401 Unauthorized“请求需要用户 认证“所以如果你是未经身份验证的401是正确的答案。如果你是未经授权的(在语义上正确的意义上),那么403就是正确的答案。 - Zaid Masud
2616应该被烧掉。几个较新的RFC更加清晰,需要区分“我不认识你”和“我认识你,但你无法访问它”。有 没有 正当理由承认存在永远不会实现(或未通过http实现)的资源,这就是403-truthers所建议的。 - Michael Blackburn


我认为重要的是要考虑到,对于浏览器,401启动用户输入新凭证的验证对话框,而403则不然。浏览器认为,如果返回401,则用户应重新进行身份验证。因此401代表无效认证,而403代表缺乏许可。

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

  • 资源需要身份验证但是 没有凭据 是 规定

401:客户端应指定凭据。

  • 指定的凭据位于 无效的格式

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

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

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

  • 指定的 证书 是 无效 但是指定有效用户(或者不要将用户指定为指定用户)。

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

  • 指定的 证书 有 过期

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

  • 指定的凭据完全有效,但不是 满足 特别的 资源,虽然有更多权限的凭证可能。

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

  • 特别的 资源 是 人迹罕至 无论凭据如何。

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

  • 指定的凭据完全有效,但具体 客户 是 受阻 从使用它们。

403:如果客户端被阻止,指定新凭据将不会执行任何操作。


3
2018-06-02 23:34