403 Forbidden vs 401未经授权的HTTP响应

对于一个存在的网页,但是没有足够权限的用户(他们没有login或不属于正确的用户组),什么是正确的HTTP响应服务? 401? 403? 别的东西? 到目前为止,我读过的每一篇文章都不太清楚两者的区别。 哪些用例适用于每个响应?

Daniel Irvine的一个明确的解释:

401 Unauthorized存在一个问题,HTTP身份validation错误代码。 这就是它:它是为了validation,而不是授权。 收到一个401响应是服务器告诉你,“你没有通过身份validation,或者根本没有通过身份validation,或者validation不正确,但是请重新validation并重试。”为了帮助你,它总是包含一个WWW-Authenticate头文件如何authentication。

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

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

所以,为了授权,我使用了403 Forbidden响应。 这是永久性的,它与我的应用程序逻辑联系在一起,比401更具体。

收到403响应是服务器告诉你,“我很抱歉。 我知道你是谁 – 我相信你说你是谁 – 但你没有权限访问这个资源。 也许如果你很好地问系统pipe理员,你会得到许可。 但请不要再困扰我,直到你的困境改变。

总而言之,应该使用401未经授权的响应来进行身份validation失败或者错误,并且之后应当使用403禁止响应,当用户通过身份validation但未被授权对给定资源执行请求的操作时。

如何使用http状态码的另一个很好的图片格式 。

请参阅RFC2616 :

401未经授权:

如果请求已经包含了授权凭证,那么401响应表明这些凭证的授权已被拒绝。

403禁止:

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

更新

从你的用例来看,用户似乎没有被authentication。 我会返回401。


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

缺less其他答案的是,必须明白,RFC 2616中的authentication和授权仅涉及RFC 2617的HTTPauthentication协议.HTTP状态代码不支持RFC2617以外的scheme进行authentication,并且不考虑当决定是否使用401或403 ..

简而言之,Terse

未经授权表示客户端未经RFC2617authentication且服务器正在启动authentication过程。 Forbidden指示客户端是经过RFC2617authentication的,没有授权,或者服务器不支持请求资源的RFC2617。

这意味着如果你有自己的自己的login过程,并且从来不使用HTTPauthentication,403总是正确的响应,401永远不会被使用。

详细和深入

从RFC2616

10.4.2 401未经授权

该请求需要用户authentication。 响应必须包含一个WWW-Authenticate头域(14.47节),其中包含一个适用于所请求资源的挑战。 客户端可以用适当的授权头域来重复请求(见14.8节)。

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

首先要记住的是本文档中的“authentication”和“授权”特指RFC 2617的HTTPauthentication协议。它们不涉及任何可能创build的自己的authentication协议使用login页面等。我将使用“login”来引用除RFC2617以外的方法的authentication和授权

所以真正的区别不在于问题是什么,即使有解决scheme。 不同的是服务器期望客户端接下来要做的事情。

401表示无法提供资源,但服务器正在请求客户端通过HTTPauthenticationlogin,并发送了回复头来启动该进程。 可能有授权可以访问资源,可能没有,但让我们试试看看会发生什么。

403表示资源不能提供,对于当前用户,没有办法通过RFC2617来解决这个问题,也没有任何意义。 这可能是因为已知没有足够的身份validation(例如由于IP黑名单),但可能是因为用户已经通过身份validation,并且没有权限。 RFC2617模型是一个用户,一个凭证,所以用户可能拥有第二组可以被授权的凭证的情况可能被忽略。 它既不暗示也不暗示某种login页面或其他非RFC2617authentication协议可能或不可能帮助 – 这是RFC2616标准和定义之外的。


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

根据RFC 2616 (HTTP / 1.1)403发送时:

服务器了解请求,但拒绝履行。 授权不起作用,请求不应重复。 如果请求方法不是HEAD,服务器希望公开为什么请求没有被满足,那么它应该描述拒绝的原因。 如果服务器不希望将这些信息提供给客户端,则可以使用状态码404(Not Found)

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

如果作为另一个用户的身份validation将授予访问所请求的资源,那么应该返回401 Unauthorized。 当访问资源被禁止给每个人或限制到一个给定的networking,或只允许通过SSL,只要它与authentication无关,最常使用Forbidden。

RFC 7235(超文本传输​​协议(HTTP / 1.1):authentication):

3.1。 401未经授权

401(未授权)状态码指示该请求尚未应用,因为它缺less有效的目标资源的身份validation凭据。 源服务器务必发送一个至less包含一个适用于目标资源的挑战的WWW-Authenticate头域(4.4节)。 如果请求中包含authentication凭证,则401响应表明授权已被拒绝 。 客户端可以用新的或replace的授权标头字段重复请求(4.1节)。 如果401响应包含与先前响应相同的挑战,并且用户代理已经尝试了至less一次authentication,则用户代理应该向用户呈现所包含的表示,因为它通常包含相关的诊断信息。

这是从RFC 2616:

10.4.4 403禁止

服务器了解请求,但拒绝履行。
授权不起作用 ,请求不应重复。
如果请求方法不是HEAD并且服务器想要创build
公众为什么要求没有得到履行,它应该描述在实体拒绝的原因。 如果服务器不希望将这个信息提供给客户端,则状态码404
(未find)可以用来代替。

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

6.5.3。 403禁止

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

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

希望“隐藏”当前存在的原始服务器
被禁止的目标资源可以用一个状态码来反应
404(未find)。

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

TL; DR版本

检查通常按以下顺序完成:

  • 401如果没有login或会话过期
  • 404如果资源不存在(也许检查,db,…昂贵)
  • 403如果用户没有权限访问资源

UNAUTHORIZED :状态码(401),表示请求需要validation 。 用户/代理服务器未知。 可以重复使用其他凭据。 注意:这是令人困惑的,因为这应该被命名为“未经authentication”。

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

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

这是一个较老的问题,但从未真正提出过的一个select是返回404。从安全angular度来看,答案最高的答案存在潜在的信息泄漏漏洞 。 比如说,所讨论的安全网页是一个系统pipe理页面,或者更常见的是用户无法访问的系统logging。 理想情况下,您不希望恶意用户甚至知道那里有一个页面/logging,更不用说他们没有访问权限。 当我构build这样的东西时,我会尝试在内部日志中logging未authentication/未授权的请求,但返回404。

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

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

本草案中的第6.5.3节 (由Fielding和Reschke撰写)给出的状态代码403与RFC 2616中logging的状态代码略有不同。

它反映了一些stream行的networking服务器和框架采用的authentication和授权scheme中发生的情况。

我强调了我认为最显着的一点。

6.5.3。 403禁止

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

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

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

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

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

你已经陈述了两个不同的案例。 每个案件应该有不同的回应:

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

实际例子

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

如果nginxfind一个文件,但没有访问权限 (用户/组)读取/访问它,它会回应403 Forbidden

RFC(2616第10节)

401未经授权(10.4.2)

含义1: 需要authentication

该请求需要用户authentication。 …

含义2: authentication不足

…如果请求已包含授权凭证,则401响应表示授权已被拒绝。 …

403禁止(10.4.4)

含义: 与authentication无关

…授权不会帮助…

更多细节:

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

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

  • 可以使用状态码404(Not Found)

    (如果服务器想要保留来自客户端的这个信息)

TL; DR

  • 401:每个拒绝与authentication有关
  • 403:每一个拒绝与authentication没有任何关系

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

401:你需要HTTP基本validation才能看到这个。

403:你看不到这个,HTTP基本authentication不会帮忙。

如果用户只需要使用您的网站的标准HTMLlogin表单login,则401将不适用,因为它特定于HTTP基本authentication。

我不推荐使用403拒绝访问像/includes这样的东西,因为就networking而言,这些资源根本就不存在,因此应该是404。

这留下403作为“你需要login”。

换句话说,403意味着“这个资源需要某种forms的authentication,而不是HTTP基本authentication”。

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

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

似乎有一个关于你自己的login问题(应用程序)的问题。

在这种情况下,除非您使用HTTP身份validation与login页面(不绑定到设置HTTP身份validation),否则根本不login不足以发送401或403。 这听起来像你可能正在寻找一个“201创build”,与你自己的login屏幕出现(而不是所请求的资源)的应用程序级访问文件。 这说:

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