403禁止与401未经授权的HTTP响应

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

401 Unauthorized
403 Forbidden
还有什么?

到目前为止,我所读到的每一个都不太清楚两者之间的区别。什么用例适合每个响应?

1367797 次浏览

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

服务器理解请求,但拒绝执行。授权没有帮助,请求不应该重复。如果请求方法不是HEAD,服务器希望公开请求未实现的原因,应该在实体中描述拒绝的原因。如果服务器不希望将这些信息提供给客户端,可以使用状态代码404(未找到)

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

来自丹尼尔·欧文[原始链接]的明确解释:

身份验证错误的HTTP状态代码401未授权有问题。仅此而已:它用于身份验证,而不是授权。收到401响应是服务器告诉你,“你不是身份验证-要么根本没有身份验证,要么经过身份验证错误-但请重新验证并重试。“为了帮助您,它将始终包含一个WWW认证标头,描述如何来验证。

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

这也是非常暂时的;服务器要求您尝试又来了

因此,对于授权,我使用403禁止响应。它是永久的,它与我的应用程序逻辑相关联,并且它更具体#36825;了401.

收到403响应是服务器告诉你,“对不起。我知道你是谁-我相信你说你是谁-但你只是没有访问此资源的权限。也许如果你问系统你会得到许可的但请别费心了直到你的困境改变”

总之,应该使用401未授权响应来丢失或错误的身份验证,应该使用403禁止响应之后,当用户经过身份验证但未被授权时对给定资源执行请求的操作。

另一个关于如何使用超文本传输协议状态码的漂亮的图形格式

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

你陈述了两个不同的案例;每个案例都应该有不同的反应:

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

关于RFC的说明基于收到的对此答案的评论:

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

"请求需要用户权限校验。"

如果您未经认证,401是正确的响应。然而,如果您未经授权,从语义上正确的意义上讲,403是正确的响应。

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

简明扼要

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

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

详细而深入

来自rfc2616

10.4.2 401未经授权

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

10.4.4 403禁止服务器理解请求,但拒绝满足它。授权无济于事,请求不应重复。

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

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

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

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


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

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

当每个人都禁止访问资源或仅限于给定网络或仅允许通过SSL访问资源时,使用403禁止,只要它与HTTP身份验证无关。

如果HTTP身份验证未使用并且服务具有基于cookie的身份验证方案,这是当今的常态,那么应该返回403或404。

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

3.1.401未经授权

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

403(和404)的语义学随着时间的推移发生了变化。这是从1999年开始的(rfc2616):

10.4.4 403禁止

授权不会有帮助并且请求不应该被重复。如果请求方法不是HEAD,并且服务器希望公开请求未被满足的原因,它应该在实体中描述拒绝的原因。如果服务器不希望将此信息提供给客户端,可以使用状态代码404(未找到)。

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

6.5.3.403禁止

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

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

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

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

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

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

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

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

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

6.5.3.403禁止

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

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

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

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

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

似乎有一个关于滚动自己登录问题(应用程序)的问题。

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

“我听到了,它在这里,但是试试这个(你不允许看到它)。

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

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

+-----------------------| RESOURCE EXISTS ? (if private it is often checked AFTER auth check)+-----------------------|       |NO |       v YESv      +-----------------------404     | IS LOGGED-IN ? (authenticated, aka user session)or      +-----------------------401        |              |403     NO |              | YES3xx        v              v401            +-----------------------(404 no reveal)       | CAN ACCESS RESOURCE ? (permission, authorized, ...)or             +-----------------------redirect          |            |to login       NO |            | YES|            |v            v403          OK 200, redirect, ...(or 404: no reveal)(or 404: resource does not exist if private)(or 3xx: redirection)

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

  • 404如果资源是公共的并且不存在或3xx重定向
  • 否则:
  • 401如果未登录或会话过期
  • 403如果用户没有权限访问资源(file, json,…)
  • 404如果资源不存在或不愿意透露任何内容,或3xx重定向

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

禁止:状态码(403)表示服务器理解请求但拒绝满足它。服务器知道但具有全权证书不足的用户/代理。重复请求将不起作用,除非凭据更改,这在短时间内是不太可能的。特殊情况:可以用来代替404,以避免在暴露资源的存在会暴露敏感数据或为攻击者提供有用信息的情况下暴露资源的存在或不存在。

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

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

!!!DEPR:答案反映了直到2014年的普遍做法!!!

太长别读

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

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

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

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

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

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

换句话说,403意味着“此资源需要HTTP基本身份验证以外的某种形式的身份验证(例如使用网站的标准超文本标记语言登录表单)”。

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

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

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

  • 资源需要身份验证,但没有证书指定

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

  • 指定的凭据位于格式错误中。

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

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

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

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

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

  • 指定的证书过期

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

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

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

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

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

  • 指定的凭据完全有效,但特定的客户端是使用它们的封锁

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

鉴于最新的RFC关于这个问题(72317235)的用例似乎很清楚(斜体是添加的):

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

401未授权

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

目标资源的响应

如果请求包含身份验证凭据,则401答复表明,已拒绝批准凭据。用户代理可以使用新的或替换了授权标头字段(第4.2节)。如果401响应包含与先前响应相同的挑战,并且用户代理已经至少尝试过一次身份验证,然后用户代理应该将封闭的表示呈现给用户,因为它通常包含相关的诊断信息。

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

403禁止

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

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

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

  • 401未授权:我不知道你是谁这是一个身份验证错误。
  • 403禁止:我知道你是谁,但你没有访问此资源的权限。

这些是含义:

401:用户未(正确)通过身份验证,资源/页面需要身份验证

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

说明:从技术上讲,403是401的超集,因为对未经身份验证的用户给予403也是合法的。无论如何,区分更有意义。

英文:

401

您可能被允许访问,但由于某种原因,您在此请求中拒绝。例如错误的密码?请根据正确的请求再试一次您将获得成功响应。

403

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

我已经为您创建了一个简单的说明,这将使它清晰。

在此处输入图片描述

401响应表示以下之一:

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

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

我对它的看法与公认的答案略有不同。

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

这是我对此的推理:

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

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

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

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

401:你是谁来着?(程序员走进没有ID或无效ID的酒吧)

403:太好了,又是你。我盯着你呢。继续,离开这里。(程序员走进他们86岁的酒吧)