인증이 필요한 리소스에 대한 올바른 http 상태 코드
사용자가 로그인이 필요한 페이지에 액세스하려고하면 반환 할 올바른 http 상태 코드에 대해 많은 혼란이있는 것 같습니다.
그러면 기본적으로 로그인 페이지를 표시 할 때 어떤 상태 코드가 전송됩니까?
4xx
범위 에서 상태 코드를 사용해야한다고 확신 합니다.
여기서는 HTTP 인증에 대해 말하는 것이 아니므로 사용하지 않을 상태 코드가 하나 이상 있습니다 ( 401 Unauthorized
).
이제 우리는 무엇을 사용해야합니까? 답변 (여기에서도 SO)은 다양한 것 같습니다.
대답에 따라 여기에 우리가 사용해야합니다 403 Forbidden
.
그러나 상태 코드에 대한 설명은 다음과 같습니다.
승인은 도움이되지 않으며 요청을 반복해서는 안됩니다.
옳지 않은 것 같습니다. 승인 이후 도움이 될 것입니다.
그래서 다른 답변을 확인해 봅시다. 대답 여기가 도 사용하지 않는 4xx
모든 아니라 용도에 범위를302 Found
302 Found
상태 코드에 대한 설명 :
요청 된 리소스는 일시적으로 다른 URI에 있습니다. 리디렉션이 가끔 변경 될 수 있으므로 클라이언트는 향후 요청에 대해 Request-URI를 계속 사용해야합니다. 이 응답은 Cache-Control 또는 Expires 헤더 필드로 표시된 경우에만 캐시 할 수 있습니다.
나는 그것도 내가 원하는 것이 아니라고 생각한다. 다른 URI에있는 요청 된 리소스가 아니기 때문입니다. 그러나 완전히 다른 리소스 (로그인 페이지 대 인증 된 콘텐츠 페이지)입니다.
그래서 나는 다른 해결책으로 놀랍게도 다른 답을 선택했습니다 .
이 대답은 우리가 400 Bad Request
.
이 상태 코드에 대한 설명은 다음과 같습니다.
잘못된 구문으로 인해 서버에서 요청을 이해할 수 없습니다. 클라이언트는 수정없이 요청을 반복해서는 안됩니다.
나는 서버가 요청을 잘 이해했다고 생각하지만 사용자가 인증되기 전에 액세스 권한을 거부합니다.
또 다른 답변 은 403
답변이 정확 하다고 말하지만 다음 과 같이 끝납니다.
세션 쿠키를 기반으로 액세스를 거부하려는 공개 웹 사이트 인 경우 [내가하는 일입니다], 로그인이 필요함을 나타내는 적절한 본문이있는 200 개 또는 로그인 페이지에 대한 302 임시 리디렉션이 자주 발생합니다. 베스트.
그래서 403
정확하지만 200
나 302
최고입니다.
야! 제가 찾고있는 것이 바로 최고의 솔루션입니다. 그러나 최고가 올바른 것과 동일해야하지 않습니까? 그리고 왜 최고일까요?
이 질문에 대해 이렇게까지 해주신 모든 분들께 감사드립니다 :)
나는 그것에 대해 너무 많이 걱정해서는 안된다는 것을 알고 있습니다. 그리고 저는이 질문이 더 가설 적이라고 생각합니다 (실제로는 아니지만 더 나은 단어가 없기 때문에 사용했습니다).
그러나이 질문은 지금 당분간 나를 괴롭 히고 있습니다.
그리고 만약 내가 매니저 였다면 (언제나 그랬던 것처럼 멋지게 들리는 단어를 집어 들었던) 나는 다음과 같이 말했을 것입니다. 그러나 그러나 그러나 평 안함이 중요합니다. :-)
그래서 : the right way™
위의 상황에서 상태 코드를 사용하는 것은 무엇 입니까 (있는 경우)?
tl; dr
사용자가 로그인이 필요한 페이지에 액세스하려고 할 때 올바른 http 상태 코드 응답은 무엇입니까?
사용자 가 자격 증명을 제공하지 않았고 API에 자격 증명이 필요한 경우 401 - Unauthorized
. 그것은 클라이언트에게 그렇게하도록 도전 할 것입니다. 일반적으로이 특정 시나리오에 대한 논쟁은 거의 없습니다.
사용자가 유효한 자격 증명을 제공했지만 요청 된 리소스에 액세스하는 데 충분하지 않은 경우 (아마도 자격 증명은 부분 유료화 계정에 대한 것이지만 요청 된 리소스는 유료 사용자에게만 해당됨) 몇 가지 옵션이 있습니다. HTTP 코드 정의 :
- 반환
403 - Forbidden
. 이것은 더 설명적이고 일반적으로 "제공된 자격 증명이 유효했지만 여전히 액세스 권한을 부여하기에 충분하지 않았습니다" 로 이해됩니다. - 반환
401 - Unauthorized
. 보안에 대한 편집증이 있다면 위의 (1)에서 반환 된 추가 정보를 클라이언트에게 다시 제공하고 싶지 않을 수 있습니다. 401
또는403
액세스가 거부 된 이유를 설명하는 유용한 정보를 응답 본문에 반환합니다 . 다시 말하지만, 해당 정보는 공격자에게 어느 정도 도움이되는 경우 제공하려는 정보보다 많을 수 있습니다.
개인적으로 유효한 자격 증명이 전달되었지만 연결된 계정에 요청 된 리소스에 대한 액세스 권한이없는 시나리오에서 항상 # 1을 사용했습니다.
"최고", "올바른 방법"및 "올바른"을 차례로 요청하면 이러한 기준이 반드시 호환되지 않고 실제로 충돌 할 수 있기 때문에이 질문에 답하기가 어렵습니다. 특히 RESTfulness와 관련하여 특히 그렇습니다. .
"최상의"대답은 응용 프로그램에 따라 다릅니다. POBB (Plain Old Browser-Based) 웹 애플리케이션을 구축하고 있습니까? 네이티브 클라이언트 (예 : iOS 또는 Android)를 구축하고 웹을 통해 서비스를 사용하고 있습니까? 웹 페이지 업데이트를 위해 AJAX를 많이 사용하고 있습니까? 컬이 의도 한 클라이언트입니까?
기존 웹 애플리케이션을 빌드한다고 가정 해 보겠습니다. Google이 수행하는 방식을 살펴 보겠습니다 (간결성을 위해 잘린 출력).
$ curl -v http://gmail.com/
< HTTP/1.1 301 Moved Permanently
< Location: http://mail.google.com/mail/
< Content-Type: text/html; charset=UTF-8
< Content-Length: 225
< ...
Google은 먼저 302 리디렉션을 사용하여 Gmail의 '실제'URL로 리디렉션합니다.
$ curl -v http://mail.google.com/mail/
< HTTP/1.1 302 Moved Temporarily
< Location: https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1<mpl=default<mplcache=2
< Content-Type: text/html; charset=UTF-8
< Content-Length: 352
< ...
그런 다음 302 리디렉션을 사용하여 로그인 페이지로 리디렉션합니다.
$ curl -v 'https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1<mpl=default<mplcache=2'
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< ...
로그인 페이지 자체 는 200 상태 코드와 함께 제공됩니다 !
왜 이렇게?
사용자 경험 관점에서 사용자가 인증되지 않아서 볼 수없는 페이지로 이동하는 경우 사용자를 로그인을 통해 수정할 수있는 페이지로 이동하려고합니다. 이 예에서 로그인 페이지는 독립적이고 다른 페이지 일뿐입니다 (이 때문에 200이 적절합니다).
설명과 로그인 페이지 링크가있는 4XX 페이지를 표시 할 수 있습니다. 실제로 더 RESTful 해 보일 수 있습니다 . 그러나 그것은 더 나쁜 사용자 경험입니다.
좋습니다.하지만 403과 같은 것이 의미가있는 경우가 있습니까? 물론.
그러나 먼저 403은 사양에 잘 정의되어 있지 않습니다. 그것이 어떻게 사용되어야하는지 이해하기 위해서는 그것이 현장에서 어떻게 구현되는지 살펴 봐야합니다.
403은 일반적으로 Apache 및 IIS와 같은 웹 서버에서 브라우저가 디렉토리 목록 ( "/"로 끝나는 URI)을 요청할 때 반환되는 페이지의 상태 코드로 사용되지만 서버에서 디렉토리 목록이 비활성화되어 있습니다. 이 경우 403은 실제로 전문화 된 404이며 사용자에게 무엇이 잘못되었는지 알려주는 것 외에는 할 수있는 일이별로 없습니다.
그러나 다음은 403을 사용하여 사용자에게 충분한 권한이 없다는 신호 와 상황을 해결하기 위해 취해야 할 조치를 알리는 사이트의 예입니다 ( 자세한 내용 은 전체 응답 을 확인하세요).
curl -v http://www.w3.org/Protocols/rfc2616/
< HTTP/1.1 403 Forbidden
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 1564
< ...
(As an aside, 403 is also seen in web-based APIs, like Twitter's API; here, 403 means "The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits.")
As an improvement, let's assume, however, that you don't want to redirect the user to a login page, or force the user to follow a link to the login page. Instead, you want to display the login form on the page that the user is prevented from seeing. If they successfully authenticate, they see the content when the page reloads; if they fail, they get the login form again. They never navigate to another URL.
In this case, a status code of 403 makes a lot of sense, and is homologous to the 401 case, with the caveat that the browser won't pop up a dialog asking the user to authenticate -- the form is in the page itself.
This approach to authentication is not common, but it could make sense, and is IMHO preferable to the pop-up-a-javascript-modal-to-log-in solutions that developers try to implement.
It comes down to the question, do you want to redirect or not?
Additional: thoughts about the 401 status code...
The 401 status code -- and associated basic/digest authentication -- has many things going for it. It's embraced by the HTTP specification, it's supported by every major browser, it's not inherently un-RESTful... The problem is, from a user experience perspective, it's very very unattractive. There's the un-stylable, cryptic pop-up dialog, lack of an elegant solution for logging out, etc. If you (or your stakeholders/clients) can live with those issues (a big if) then it might qualify as the "correct" solution.
Agreed. REST is just a style, not a strict protocol. Many public web services deviate from this style. You can build your service to return whatever you want. Just make sure your clients know how what return codes to expect.
Personally, I have always used 401 (unauthorized) to indicate an unauthenticated user has requested a resource that requires a login. I then require the client application to guide the user to the login.
I use 400 (bad request) in response to a logon attempt with invalid credentials.
HTTP 302 (moved) seems more appropriate for web applications where the client is a browser. Browsers typically follow the re-direct address in the response. This can be useful for guiding the user to a logon page.
I'm not talking about HTTP authentication here, so that's at least 1 status code we aren't going to use (401 Unauthorized).
Wrong. 401 is part of Hypertext Transfer Protocol (RFC 2616 Fielding, et al.), but not limited to HTTP authentication. Furthermore, it's the only status code indicating that the request requires user authentication.
302 & 200 codes could be used and is easier to implement in some scenarios, but not all. And if you want to obey the specs, 401 is the only correct answer there is.
And 403 is indeed the most wrong code to return. As you correctly stated...
Authorization will not help and the request SHOULD NOT be repeated.
So this is clearly not suitable to indicate that authorization is an option.
I would stick to the standard: 401 Unauthorized
-
UPDATE
To add a little more info, lifting the confusion related to...
The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource.
If you think that's going to stop you from using a 401, you have to remember there's more:
"The field value consists of at least one challenge that indicates the authentication scheme(s) and parameters applicable to the Request-URI."
This "indicating the authentication scheme(s)" means you can opt-in for other auth-schemes!
The HTTP protocol (RFC 2616) defines a simple framework for access authentication schemes, but you don't HAVE to use THAT framework.
In other words: you're not bound to the usual WWW-Auth. You only just MUST indicate HOW your webapp does it's authorization and offer the according data in the header, that's all. According to the specs, using a 401, you can choose your own poison of authorization! And that's where your "webapp" can do what YOU want it to do when it comes to the 401 header and your authorization implementation.
Don't let the specs confuse you, thinking you HAVE to use the usual HTTP authentication scheme. You don't! The only thing the specs really enforce: you just HAVE/MUST identify your webapp's authentication scheme and pass on related parameters to enable the requesting party to start potential authorization attempts.
And if you're still unsure, I can put all this into a simple but understandable perspective: let's say you're going to invent a new authorization scheme tomorrow, then the specs allow you to use that too. If the specs would have restricted implementation of such newer authorization technology implementations, those specs would've been modified ages ago. The specs define standards, but they do not really limit the multitude of potential implementations.
Your "TL;DR" doesn't match the "TL" version.
The proper response for requesting a resource that you need authorization to request, is 401.
302 is not the proper response, because, in fact, the resource is not available some place else. The original URL was correct, the client simply didn't have the rights. If you follow the redirect, you do not actually get what you're looking for. You get dropped in to some ad hoc workflow that has nothing to do with the resource.
403 is incorrect. 403 is the "can't get there from here" error. You simply can't see this, I don't care who you are. Some would argue 403 and 404 are similar. The difference is simply with 403, the server is saying "yea, I have it, but you can't", whereas 404 says "I know nothing about what you're talking about." Security wonks would argue that 404 is "safer". Why tell them something they don't need to know.
The problem you are encountering has nothing to do with REST or HTTP. Your problem is trying to set up some stateful relationship between the client and server, manifested in the end via some cookie. The whole resource -> 302 -> Login page is all about user experience using the hack that's known as the Web Browser, which happens to be both, in stock form, a lousy HTTP client and a lousy REST participant.
HTTP has an authorization mechanism. The Authorization header. The user experience around it, in a generic browser, is awful. So no one uses it.
So there is not proper HTTP response (well there is, 401, but don't/can't use that). There is not proper REST response, as REST typically relies on the underlying protocol (HTTP in this case, but we've tackled that already).
So. 302 -> 200 for the login page is all she wrote. That's what you get. If you weren't using the browser, or did everything via XHR or some other custom client, this wouldn't be an issue. You'd just use Authorization header, follow the HTTP protocol, and leverage a scheme like either DIGEST or what AWS uses, and be done. Then you can use the appropriate standards to answer questions like these.
As you point out, 403 Forbidden
is explicitly defined with the phrase "Authorization will not help", but it is worth noting that the authors were almost certainly referring here to HTTP authorization (which will indeed not help as your site uses a different authorization scheme). Indeed, given that the status code is a signal to the user agent rather than the user, such a code would be correct insofar as any authorization the agent attempts to provide will not assist any further with the required authorization process (c.f. 401 Unauthorized
).
However, if you take that definition of 403 Forbidden
literally and feel it is still inappropriate, perhaps 409 Conflict
might apply? As defined in RFC 2616 §10.4.10:
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
There is indeed a conflict with the current state of the resource: the resource is in a "locked" state and such conflict can only be "resolved" through the user providing their credentials and resubmitting the request. The body will include "enough information for the user to recognize the source of the conflict" (it will state that they are not logged-in) and indeed will also include "enough information for the user or user agent to fix the problem" (i.e. a login form).
Your Answer:
401 Unauthorized
especially if you do not care or will not be redirecting people to a login page
-or-
302 Found
to imply there was the resource but they need to provide credentials to be returned to it. Do this only if you will be using a redirect and make sure to provide appropriate information in the body of the response.
Other Suggestions:
401 Unauthorized
is generally used for resources the user does not have access to after handling authentication.
403 Forbidden
is a little obscure to me in honesty. I use it when I lock down resources from the file system level, and like your post said, "authorization does not help".
400 Bad Request
is inappropriate as needing to login does not represent malformed syntax.
I believe 401 is the correct status code to return from failed authorization. Reference RFC 2616 section-14.8 It reads "A user agent that wishes to authenticate itself with a server-- usually, but not necessarily, after receiving a 401 response"
ReferenceURL : https://stackoverflow.com/questions/8389253/correct-http-status-code-for-resource-which-requires-authorization
'IT story' 카테고리의 다른 글
org.eclipse.m2e : lifecycle-mapping에 대한 POM을 찾을 수 없음 경고 제거 (0) | 2020.12.30 |
---|---|
C 프로그램에서 fclose ()를 호출하지 않으면 어떻게됩니까? (0) | 2020.12.30 |
Visual Studio 2012 또는 2013의 Emacs 키 바인딩 (0) | 2020.12.30 |
C # 문자열의 GetHashCode ()는 어떻게 구현됩니까? (0) | 2020.12.30 |
System.Web.Http.Owin은 어떻게 얻습니까? (0) | 2020.12.30 |