403 Forbidden 与 401 Unauthorized HTTP 响应
对于存在的网页,但用户没有足够的权限(他们未登录或不属于正确的用户组),要提供的正确 HTTP 响应是什么?
401 未经授权
?
403 禁止
?
还有别的事吗?
到目前为止,我所读到的关于两者之间的区别还不是很清楚。每个响应适合哪些用例?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(22)
来自丹尼尔·欧文 [原始链接]:
另一种漂亮的图片格式说明了如何使用http状态代码。
A clear explanation from Daniel Irvine [original link]:
Another nice pictorial format of how http status codes should be used.
编辑:RFC2616已过时,请参阅RFC9110。
401 未经授权:
第403章 禁止:
从您的用例来看,该用户似乎未经过身份验证。我会返回401。
Edit: RFC2616 is obsolete, see RFC9110.
401 Unauthorized:
403 Forbidden:
From your use case, it appears that the user is not authenticated. I would return 401.
其他答案缺少的一点是,必须理解 RFC 2616 上下文中的身份验证和授权仅指 RFC 2617 的 HTTP 身份验证协议。HTTP 状态代码不支持通过 RFC2617 之外的方案进行身份验证,因此不考虑在决定使用 401 还是 403 时。Brief
and Terse
Unauthorized 表示客户端未经过 RFC2617 身份验证,并且服务器正在启动身份验证过程。 Forbidden 表示客户端已通过 RFC2617 身份验证但没有授权,或者服务器不支持请求资源的 RFC2617。
这意味着如果您有自己的登录流程并且从不使用 HTTP 身份验证,则 403 始终是正确的响应,并且永远不应该使用 401。
详细和深入
RFC2616 的
和
首先要记住的是,本文档上下文中的“身份验证”和“授权”特指 RFC 2617 中的 HTTP 身份验证协议。它们并不指您可能创建的任何自定义身份验证协议使用登录页面等。我将使用“登录”来指代通过 RFC2617 以外的方法进行身份验证和授权,
因此真正的区别不是问题是什么,也不是是否有解决方案。区别在于服务器期望客户端下一步做什么。
401 表示无法提供资源,但服务器正在请求客户端通过 HTTP 身份验证登录,并已发送回复标头来启动该过程。可能有允许访问资源的授权,也可能没有,但让我们尝试一下,看看会发生什么。
403表示无法提供资源,对于当前用户来说,没有办法通过RFC2617解决这个问题,也没有尝试的意义。这可能是因为已知任何级别的身份验证都是不够的(例如,由于 IP 黑名单),但也可能是因为用户已经经过身份验证并且没有权限。 RFC2617 模型是单用户、单凭证,因此用户可能拥有第二组可授权凭证的情况可以被忽略。它既不暗示也不暗示某种登录页面或其他非 RFC2617 身份验证协议可能有帮助,也可能没有帮助 - 这超出了 RFC2616 标准和定义。
编辑:RFC2616已过时,请参阅RFC7231 和 RFC7235。
Something the other answers are missing is that it must be understood that Authentication and Authorization in the context of RFC 2616 refers ONLY to the HTTP Authentication protocol of RFC 2617. Authentication by schemes outside of RFC2617 is not supported in HTTP status codes and are not considered when deciding whether to use 401 or 403.
Brief and Terse
Unauthorized indicates that the client is not RFC2617 authenticated and the server is initiating the authentication process. Forbidden indicates either that the client is RFC2617 authenticated and does not have authorization or that the server does not support RFC2617 for the requested resource.
Meaning if you have your own roll-your-own login process and never use HTTP Authentication, 403 is always the proper response and 401 should never be used.
Detailed and In-Depth
From RFC2616
and
The first thing to keep in mind is that "Authentication" and "Authorization" in the context of this document refer specifically to the HTTP Authentication protocols from RFC 2617. They do not refer to any roll-your-own authentication protocols you may have created using login pages, etc. I will use "login" to refer to authentication and authorization by methods other than RFC2617
So the real difference is not what the problem is or even if there is a solution. The difference is what the server expects the client to do next.
401 indicates that the resource can not be provided, but the server is REQUESTING that the client log in through HTTP Authentication and has sent reply headers to initiate the process. Possibly there are authorizations that will permit access to the resource, possibly there are not, but let's give it a try and see what happens.
403 indicates that the resource can not be provided and there is, for the current user, no way to solve this through RFC2617 and no point in trying. This may be because it is known that no level of authentication is sufficient (for instance because of an IP blacklist), but it may be because the user is already authenticated and does not have authority. The RFC2617 model is one-user, one-credentials so the case where the user may have a second set of credentials that could be authorized may be ignored. It neither suggests nor implies that some sort of login page or other non-RFC2617 authentication protocol may or may not help - that is outside the RFC2616 standards and definition.
Edit: RFC2616 is obsolete, see RFC7231 and RFC7235.
检查通常按以下顺序完成:
未经授权:状态代码 (401)表示请求需要身份验证,通常这意味着用户需要登录(会话)。服务器未知的用户/代理。可以用其他凭证重复。注意:这很令人困惑,因为它应该被命名为“未经身份验证”而不是“未经授权”。如果会话过期,登录后也可能发生这种情况。
特殊情况:可以用来代替 404 以避免泄露资源的存在或不存在(来源@gingerCodeNinja)
FORBIDDEN:状态代码 (403) 指示服务器理解该资源请求但拒绝履行。服务器已知的用户/代理,但凭据不足。除非凭据发生更改,否则重复请求将不起作用,而这在短时间内不太可能发生。
特殊情况:可以用来代替 404,以避免泄露资源的存在或不存在(鸣谢 @gingerCodeNinja),以防泄露资源的存在会暴露敏感数据或向攻击者提供有用的信息。
NOT FOUND:状态代码 (404) 指示所请求的资源不可用。用户/代理已知,但服务器不会透露有关资源的任何信息,就好像它不存在一样。重复不会有效果。这是 404 的特殊用途(github 就是这样做的)。
正如 @ChrisH 提到的,有一些重定向选项 3xx (301、302、303、307 或根本不重定向并使用 401):
Checks are usually done in this order:
UNAUTHORIZED: Status code (401) indicating that the request requires authentication, usually this means user needs to be logged-in (session). User/agent unknown by the server. Can repeat with other credentials. NOTE: This is confusing as this should have been named 'unauthenticated' instead of 'unauthorized'. This can also happen after login if session expired.
Special case: Can be used instead of 404 to avoid revealing presence or non-presence of resource (credits @gingerCodeNinja)
FORBIDDEN: Status code (403) indicating the server understood the request but refused to fulfill it. User/agent known by the server but has insufficient credentials. Repeating request will not work, unless credentials changed, which is very unlikely in a short time span.
Special case: Can be used instead of 404 to avoid revealing presence or non-presence of resource (credits @gingerCodeNinja) in the case that revealing the presence of the resource exposes sensitive data or gives an attacker useful information.
NOT FOUND: Status code (404) indicating that the requested resource is not available. User/agent known but server will not reveal anything about the resource, does as if it does not exist. Repeating will not work. This is a special use of 404 (github does it for example).
As mentioned by @ChrisH there are a few options for redirection 3xx (301, 302, 303, 307 or not redirecting at all and using a 401):
根据 RFC 2616 (HTTP/1.1) 403 是发送时间:
,如果客户端可以通过身份验证访问资源,则应发送 401。
According to RFC 2616 (HTTP/1.1) 403 is sent when:
In other words, if the client CAN get access to the resource by authenticating, 401 should be sent.
假设 HTTP 身份验证(WWW-Authenticate 和 Authorization 标头)正在使用,如果以其他用户身份进行身份验证将授予访问所请求的资源,则应返回 401 Unauthorized。
当禁止所有人访问资源或仅限于给定网络或仅允许通过 SSL 访问资源时,将使用 403 Forbidden,只要与 HTTP 身份验证无关即可。
如果未使用 HTTP 身份验证,并且服务具有基于 cookie 的身份验证方案(这是当今的标准),则应返回 403 或 404。
关于 401,这来自 RFC 7235(超文本传输协议 (HTTP/1.1):身份验证):
403(和 404)的语义随着时间的推移而发生了变化。这是 1999 年的内容 (RFC 2616):
2014 年 RFC 7231(超文本传输协议 (HTTP/1.1):语义和内容)改变了403的含义:
因此,403(或 404)现在可能意味着任何事情。提供新的凭据可能会有所帮助……也可能不会。
我相信这种情况发生变化的原因是 RFC 2616 假设当今的 Web 应用程序在实践中使用表单和 cookie 构建自定义身份验证方案时将使用 HTTP 身份验证。
Assuming HTTP authentication (WWW-Authenticate and Authorization headers) is in use, if authenticating as another user would grant access to the requested resource, then 401 Unauthorized should be returned.
403 Forbidden is used when access to the resource is forbidden to everyone or restricted to a given network or allowed only over SSL, whatever as long as it is no related to HTTP authentication.
If HTTP authentication is not in use and the service has a cookie-based authentication scheme as is the norm nowadays, then a 403 or a 404 should be returned.
Regarding 401, this is from RFC 7235 (Hypertext Transfer Protocol (HTTP/1.1): Authentication):
The semantics of 403 (and 404) have changed over time. This is from 1999 (RFC 2616):
In 2014 RFC 7231 (Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content) changed the meaning of 403:
Thus, a 403 (or a 404) might now mean about anything. Providing new credentials might help... or it might not.
I believe the reason why this has changed is RFC 2616 assumed HTTP authentication would be used when in practice today's Web apps build custom authentication schemes using for example forms and cookies.
这是一个较老的问题,但从未真正提出的一个选项是返回 404。从安全角度来看,得票最高的答案可能会受到潜在的 信息泄露漏洞。例如,假设所讨论的安全网页是系统管理页面,或者更常见的是,是用户无权访问的系统中的记录。理想情况下,您不希望恶意用户知道那里有页面/记录,更不用说他们无权访问了。当我构建这样的东西时,我会尝试在内部日志中记录未经身份验证/未经授权的请求,但返回 404。
OWASP 有一些 有关攻击者如何使用此类信息作为攻击一部分的更多信息。
This is an older question, but one option that was never really brought up was to return a 404. From a security perspective, the highest voted answer suffers from a potential information leakage vulnerability. Say, for instance, that the secure web page in question is a system admin page, or perhaps more commonly, is a record in a system that the user doesn't have access to. Ideally you wouldn't want a malicious user to even know that there's a page / record there, let alone that they don't have access. When I'm building something like this, I'll try to record unauthenticate / unauthorized requests in an internal log, but return a 404.
OWASP has some more information about how an attacker could use this type of information as part of an attack.
这个问题很早以前就被问过,但人们的思考仍在继续。
第 6.5.3 节 为状态代码 403 赋予的含义与 RFC 2616。
它反映了身份验证和验证过程中发生的情况。许多流行的网络服务器和框架采用的授权方案。
我强调了我认为最重要的一点。
无论您使用什么约定,重要的是在您的站点/API 中提供统一性。
This question was asked some time ago, but people's thinking moves on.
Section 6.5.3 in this draft (authored by Fielding and Reschke) gives status code 403 a slightly different meaning to the one documented in RFC 2616.
It reflects what happens in authentication & authorization schemes employed by a number of popular web-servers and frameworks.
I've emphasized the bit I think is most salient.
Whatever convention you use, the important thing is to provide uniformity across your site / API.
这些含义如下:
401:用户未(正确)经过身份验证,资源/页面需要身份验证
403:用户的角色或权限不允许访问所请求的资源,例如用户不是管理员,请求的页面供管理员使用。
注意:从技术上讲,403 是 401 的超集,因为为未经身份验证的用户提供 403 也是合法的。无论如何,区分更有意义。
These are the meanings:
401: User not (correctly) authenticated, the resource/page require authentication
403: User's role or permissions does not allow to access requested resource, for instance user is not an administrator and requested page is for administrators.
Note: Technically, 403 is a superset of 401, since is legal to give 403 for unauthenticated user too. Anyway is more meaningful to differentiate.
<强>!!! DEPR:答案反映了 2014 年之前的常见做法!!!
TL;DR
实际示例
如果 < strong>apache 需要身份验证(通过
.htaccess
),并且您点击取消
,它将以401响应需要授权
如果 nginx 找到一个文件,但没有访问权限(用户/组)来读取/访问它,它将响应
403禁止
RFC (2616 第 10 节)
401 未经授权 (10.4.2)
含义 1:需要身份验证
含义2:身份验证不足
403 Forbidden (10.4.4)
含义:与身份验证无关
更多详细信息:
(如果服务器希望向客户端保留此信息)
!!! DEPR: The answer reflects what used to be common practice, up until 2014 !!!
TL;DR
Practical Examples
If apache requires authentication (via
.htaccess
), and you hitCancel
, it will respond with a401 Authorization Required
If nginx finds a file, but has no access rights (user/group) to read/access it, it will respond with
403 Forbidden
RFC (2616 Section 10)
401 Unauthorized (10.4.2)
Meaning 1: Need to authenticate
Meaning 2: Authentication insufficient
403 Forbidden (10.4.4)
Meaning: Unrelated to authentication
More details:
(If the server wants to keep this information from client)
401
响应代码表示以下情况之一:另一方面,
403
响应代码意味着访问令牌确实有效,但用户没有适当的权限来执行请求的操作。401
response code means one of the following:A
403
response code on the other hand means that the access token is indeed valid, but that the user does not have appropriate privileges to perform the requested action.我为您创建了一个简单的注释,可以清楚地说明这一点。
I have created a simple note for you which will make it clear.
您已经陈述了两种不同的情况;每种情况应该有不同的响应:
根据收到的对此答案的评论,对 RFC 进行注释:
如果用户未登录,则他们未经身份验证,其对应的 HTTP 是 401,并且被误导性地称为“未经授权”在 RFC 中。正如 第 10.4.2 节所述,401 未经授权:
如果您未经身份验证,则正确的响应是 401。但是,如果您未经授权,从语义上正确的意义上来说,403 是正确的响应。
You have stated two different cases; each case should have a different response:
Note on the RFC based on comments received to this answer:
If the user is not logged in they are un-authenticated, the HTTP equivalent of which is 401 and is misleadingly called Unauthorized in the RFC. As section 10.4.2 states for 401 Unauthorized:
If you're unauthenticated, 401 is the correct response. However if you're unauthorized, in the semantically correct sense, 403 is the correct response.
401:你又是谁?(程序员走进一家没有 ID 或无效 ID 的酒吧)
403:哦,太棒了,又是你。我已经注视着你了。走吧,离开这里。(程序员走进他们 86 岁的酒吧)
401: Who are you again?? (programmer walks into a bar with no ID or invalid ID)
403: Oh great, you again. I've got my eye on you. Go on, get outta here. (programmer walks into a bar they are 86'd from)
英语:
401
403
In English:
401
403
401:您需要 HTTP 基本身份验证才能看到此内容。
如果用户只需要使用站点的标准 HTML 登录表单登录,则 401 不合适,因为它特定于 HTTP 基本身份验证。
403:此资源存在,但您无权查看它,并且 HTTP 基本身份验证无济于事。
我不建议使用 403 来拒绝访问诸如
/includes
之类的内容,因为就网络而言,这些资源根本不存在,因此应该使用 404。换句话说,403意思是“此资源需要除 HTTP 基本身份验证之外的某种形式的身份验证(例如使用网站的标准 HTML 登录表单)”。
https://www.w3.org/Protocols/rfc2616/ rfc2616-sec10.html#sec10.4.2
401: You need HTTP basic auth to see this.
If the user just needs to log in using you site's standard HTML login form, 401 would not be appropriate because it is specific to HTTP basic auth.
403: This resource exists but you are not authorized to see it, and HTTP basic auth won't help.
I don't recommend using 403 to deny access to things like
/includes
, because as far as the web is concerned, those resources don't exist at all and should therefore 404.In other words, 403 means "this resource requires some form of auth other than HTTP basic auth (such as using the web site's standard HTML login form)".
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:如果客户端被阻止,指定新凭据将不会执行任何操作。
I think it is important to consider that, to a browser, 401 initiates an authentication dialog for the user to enter new credentials, while 403 does not. Browsers think that, if a 401 is returned, then the user should re-authenticate. So 401 stands for invalid authentication while 403 stands for a lack of permission.
Here are some cases under that logic where an error would be returned from authentication or authorization, with important phrases bolded.
401: The client should specify credentials.
400: That's neither 401 nor 403, as syntax errors should always return 400.
401: The client should specify valid credentials.
401: Again, the client should specify valid credentials.
401: This is practically the same as having invalid credentials in general, so the client should specify valid credentials.
403: Specifying valid credentials would not grant access to the resource, as the current credentials are already valid but only do not have permission.
403: This is regardless of credentials, so specifying valid credentials cannot help.
403: If the client is blocked, specifying new credentials will not do anything.
鉴于有关此事的最新 RFC (7231 和 7235)用例似乎很清楚(添加斜体):
Given the latest RFC's on the matter (7231 and 7235) the use-case seems quite clear (italics added):
我的看法与已接受的答案略有不同。
当身份验证失败时返回 403,当授权失败时返回 401,这似乎更语义和逻辑。
我的理由如下:
当您请求进行身份验证时,您有权提出该请求。您需要这样做,否则一开始就没有人能够通过身份验证。
如果您的身份验证失败,您将被禁止,这在语义上是有意义的。
另一方面被禁止的也可以申请授权,但是
假设您已通过身份验证,但无权访问特定端点。返回 401 Unauthorized 似乎更语义化。
Spring Boot 的安全性会因身份验证尝试失败而返回 403
I have a slightly different take on it from the accepted answer.
It seems more semantic and logical to return a 403 when authentication fails and a 401 when authorisation fails.
Here is my reasoning for this:
When you are requesting to be authenticated, You are authorised to make that request. You need to otherwise no one would even be able to be authenticated in the first place.
If your authentication fails you are forbidden, that makes semantic sense.
On the other hand the forbidden can also apply for Authorisation, but
Say you are authenticated and you are not authorised to access a particular endpoint. It seems more semantic to return a 401 Unauthorised.
Spring Boot's security returns 403 for a failed authentication attempt
我认为这样更容易:
如果系统无法识别您使用的凭据,例如,如果它是不同的领域或其他什么,则返回 401。
如果您设法通过 401
403 如果您不被允许访问该资源,如果您在未通过身份验证时收到此消息,那么即使您通过了身份验证,您也可能不会收到它,系统不会检查您是否有或没有凭证。
披露:我还没有阅读 RFC。
I think it's easier like this:
401 if the credentials you are using is not recognized by the system, for example if it's different realm or something.
if you managed to pass 401
403 if you are not allowed to access the resource, if you get this when you are not authenticated, chances are you won't be getting it even if you are authenticated, the system doesn't check if you have credentials or not.
Disclosure: I haven't read the RFCs.
在401 vs 403的例子中,这个问题已经被回答过很多次了。这本质上是“HTTP 请求环境”的争论,而不是“应用程序”的争论。
似乎有一个关于自行登录问题(应用程序)的问题。
在这种情况下,仅仅未登录不足以发送 401 或 403,除非您使用 HTTP 身份验证而不是登录页面(与设置 HTTP 身份验证无关)。听起来您可能正在寻找“201 Created”,其中存在一个滚动您自己的登录屏幕(而不是请求的资源),用于对文件的应用程序级访问。这表示:
“我听到了,它就在这里,但试试这个(不允许你看到它)”
In the case of 401 vs 403, this has been answered many times. This is essentially a 'HTTP request environment' debate, not an 'application' debate.
There seems to be a question on the roll-your-own-login issue (application).
In this case, simply not being logged in is not sufficient to send a 401 or a 403, unless you use HTTP Auth vs a login page (not tied to setting HTTP Auth). It sounds like you may be looking for a "201 Created", with a roll-your-own-login screen present (instead of the requested resource) for the application-level access to a file. This says:
"I heard you, it's here, but try this instead (you are not allowed to see it)"