[TIL] CORS

ytwicey·2020년 11월 15일
0

TIL

목록 보기
13/23

Cominciamo

  • 우선 틀린게 있거나 잘못 이해한 것이 있다면, 댓글 남겨쥬세요.

====================================================

CORS

Cross-Origin Resource Sharing의 약자.

an HTTP-header based mechanism that allows a server to indicate any other origins (domain, protocol, or port) than its own from which a browser should permit loading of resources. CORS also relies on a mechanism by which browsers make a “preflight” request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request. By mdn

"서버가 브라우저가 리소스로드를 허용해야하는 origin이 아닌 다른 origin (도메인, 프로토콜 또는 포트)을 표시 할 수 있도록하는 HTTP 헤더 기반 메커니즘. CORS는 또한 서버가 실제 요청을 허가할 것인지 체크하기 위해 브라우저가 교차출처리소스를 호스팅하는 서버에게 preflight요청을 보내는 메커니즘에 의존한다. 그 preflight에는 브라우저는 HTTP의 메소드를 알리는 헤더를 보내고, 헤더는 (preflight가 아니라) 실제 요청에서 사용된다."

For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request resources from the same origin the application was loaded from unless the response from other origins includes the right CORS headers.

"보안상의 이유로, 브라우저는 스트립트에서 시작된 cross-origin HTTP요청을 제한한다. 예를 들어, XMLHttpRequest와 the Fetch API는 같은 origin 정책을 따른다. 다시 말하면, 다른 출처의 응답이 올바른 CORS 헤더를 포함하고 있지 않으면, 이런 API를 사용하는 웹앱은 오직 애플리케이션이 로드된 같은 origin으로부터 리소스을 요청 할 수 있다."

강의자료에서는, 추가 HTTP헤더를 사용하여 한 출처에서 실행중인 웹앱이 다른 출처의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제. 브라우저가 자발적으로 어플리케이션을 사용하는 클라이언트/유저를 보호하기 위한 방법 이라고 정리 한다.

그러니까 다시 나의 말로 정리하면,
어떤 리소스를 서버에 요청할 때, 서버는 허가된(혹은 미리 설정해둔) 클라이언트의 요청만 받아들이는데, 클라이언트에서는 그게 나인지 알 수 없으니까 미리 preflight로 떠보는 거지. 떠 봤는데 허가 되어 있으면 실제 요청을 보내는 거고. 약간 만우절 같은 느낌... 만우절에 고백하고 거절 당하면 뻥이야! 이러고 수락하면 사귀는 느낌....

위키에서 그림을 가져왔는데, 그러니까 지금 한 domain-a.com이라는 웹 애플리케이션에서 이미지를 2개를 차용하는데, 하나는 같은 출처의 웹서버에서 하나는 domain-b.com라는 웹서버에서 가져온다. 이럴 경우 같은 출처는 same-origin policy에 의해서 허용되지만, cross-origin 같은 경우는 CORS에 의해서 제어된다.

The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.

MDN에 위 그림의 사족이 위와 같이 붙어 있다.
CORS 메커니즘은 안전한 교차출처 요청과 브라우저와 서버사이의 안전한 데이터 전송을 지원한다. 모던 브라우저는 XMLHttpRequest나 Fetch와 같은 API들에서 교차출처 요청의 위함을 완화시키기 위해 CORS를 사용한다.


Functional overview
The Cross-Origin Resource Sharing standard works by adding new HTTP headers that let servers describe which origins are permitted to read that information from a web browser. Additionally, for HTTP request methods that can cause side-effects on server data (in particular, HTTP methods other than GET, or POST with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with the HTTP OPTIONS request method, and then, upon "approval" from the server, sending the actual request. Servers can also inform clients whether "credentials" (such as Cookies and HTTP Authentication) should be sent with requests.

CORS failures result in errors, but for security reasons, specifics about the error are not available to JavaScript. All the code knows is that an error occurred. The only way to determine what specifically went wrong is to look at the browser's console for details.

Subsequent sections discuss scenarios, as well as provide a breakdown of the HTTP headers used.

아무리 읽어봐도 잘 모르겠어서 한다. 번역. 읽는다. MDN

CORS표준은 서버가 어떤 출처에서 웹브라우저의 정보를 읽을 수 있을지 허락하는지 알 수 있게 하는 새로운 HTTP헤더를 추가함으로써 작동한다. 더하여 서버데이터에 부작용을 일으킬 수 있는 요청 메소드요청에 대해서,(특히 Get이외의 http메소드 혹은 미디어타입의 Post), 브라우저가 요청을 preflight하기를 강제하고, OPTIONS요청 메서드를 사용하여 서버에서 지원되는 메서드를 요청한 다음 서버에서 "승인"하면 실제 요청을 전송하도록 요구합니다. 서버는 또한 클라이언트에서 'credentials'이 요청과 함께 보내져야 하는지 아닌지를 알려줄 수 있다.

CORS의 실패는 에러를 발생시키지만, 보안의 이유로 오류에 대한 세부사항은 자바스크립트에서는 알 수 없다. 코드가 아는 것은 오류가 발생했다는 것 뿐이다.
무엇이 잘못되었는지 유일한 방법은 세부정보를 위한 브라우저 콘솔을 보는 일이다. 이후 세부시나리오에 대해서 살펴 보겠다.

Examples of access control scenarios

Simple requests

Some requests don’t trigger a CORS preflight. Those are called “simple requests” in this article, though the Fetch spec (which defines CORS) doesn’t use that term.

어떤 요청은 CORS의 preflight를 발생시키지 않는다. 물론 CORS를 정의하는 Fetch spec에서는 이 용어를 사용하지는 않지만, 우리는 그것을 이 아티클에서 simple requests라고 부를 것이다.

A “simple request” is one that meets all the following conditions:

simple request는 다음의 조건들을 모두 만족하는 것을 의미한다.

One of the allowed methods: GET, HEAD, POST

Apart from the headers automatically set by the user agent (for example, Connection, User-Agent, or the other headers defined in the Fetch spec as a “forbidden header name”), the only headers which are allowed to be manually set are those which the Fetch spec defines as a “CORS-safelisted request-header”, which are:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (but note the additional requirements below)
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

The only allowed values for the Content-Type header are:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

No event listeners are registered on any XMLHttpRequestUpload object used in the request; these are accessed using the XMLHttpRequest.upload property.
No ReadableStream object is used in the request.

이건 나중에 읽어보는 걸로... 심플리퀘스트는 preflight없음

위 그림의 예시는 클라이언트와 서버간의 단순 교환을 이행한다.

Let's look at what the browser will send to the server in this case, and let's see how the server responds:

이경우 브라우저가 서버에게 무엇을 보내는지 살펴보고, 서버가 어떻게 답하는지 보자.

상단의 요청의 Origin은 foo.example에서 발생된다는 것을 보여준다. 하단의 응답에서는 서버는 Access-Control-Allow-Origin : *는 어떤 출처든지 접근가능하다는 것을 의미한다.

다시 풀어서 보면,

이러한 패턴의 Origin과 Access-Control-Allow-Origin 헤더는 접근제어 프로토콜 사용의 가장 단순한 형태이다. 만약에 자원 소유자인 bar.other가 자원에 접근을 오직 foo.example에서의 요청으로만 제한하고 싶다면, 아래와 같이 보낼 것이다.

그러니까, simple requests에서는 단순히 preflight없이도, bar.other에서 어떤 리소스를 foo.example이 불러와서 쓰고 싶다면, 위와 같이 헤더라는 걸 써서 보내게 되는데, 서버에서 모든 Origin에서 퍼가게 하고 싶으면 Access-Control-Allow-Origin을 *으로 혹은 한 출처에서만 가져가게 하고 싶으면 Access-Control-Allow-Origin을 해당 출처로 지정하면 된다는거 같음


Preflighted requests

Unlike “simple requests” (discussed above), for "preflighted" requests the browser first sends an HTTP request using the OPTIONS method to the resource on the other origin, in order to determine if the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data.

위에서 언급한 simple requests와 달리, 먼저 보내진 요청(preflighted requests)을 위해서 브라우저는 실제 요청이 보내기에 안전한지 확인하기 위해서 OPTIONS라는 메소드를 사용해 HTTP요청을 다른 출처의 리소스에 먼저 보낸다. 교차 사이트 요청은 사용자 데이터에 영향을 줄 수 있을지도 모르기 때문에 이런 식으로 먼저 preflight요청을 하게 된다.

위 그림처럼 요청을 보내고 응답을 받음.

위는 OPTIONS 요청과 응답

Lines 1 - 10 above represent the preflight request with the OPTIONS method. The browser determines that it needs to send this based on the request parameters that the JavaScript code snippet above was using, so that the server can respond whether it is acceptable to send the request with the actual request parameters.

위 1-10번 줄은 preflight OPTIONS를 사용한 preflight 요청을 나타낸다. 브라우저는 자바스크립트 코드 스니펫이 사용중인 요청 파라미터에 기반하여 전송해야하고 따라서 서버는 실제 요청 파라미터와 함께 온 요청이 받아들여질 수 있는지 없는지를 응답할 수 있음.

쉽게 말하면, preflight가 오면, 서버는 실제 요청을 받아들일 지 말지를 응답함

OPTIONS is an HTTP/1.1 method that is used to determine further information from servers, and is a safe method, meaning that it can't be used to change the resource. Note that along with the OPTIONS request, two other request headers are sent (lines 9 and 10 respectively):

  • Access-Control-Request-Method: POST
    Access-Control-Request-Headers: X-PINGOTHER, Content-Type

OPTIONS는 HTTP/1.1의 방법으로 서버로부터 오는 추가정보를 결정하는데 사용되고, 이것은 안전한 방법이므로 리소스를 바꾸는데 사용될 수는 없음을 의미. 옵션스 리퀘스트에 따라 두개의 다른 요청헤더가 전송됨.

Lines 13 - 22 above are the response that the server sends back, which indicate that the request method (POST) and request headers (X-PINGOTHER) are acceptable. In particular, let's look at lines 16-19:

  • Access-Control-Allow-Origin: http://foo.example
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    Access-Control-Max-Age: 86400

13-22번째 줄은 서버로부터 온 응답이며, 요청 메소드(post)와 요청 헤더가 acceptable하다는 것을 알려주고 있다. 특히 16-19번재쭐을 보면 그렇다.

The server responds with Access-Control-Allow-Origin: http://foo.example, restricting access to just the requesting origin domain. It also responds with Access-Control-Allow-Methods, which says that POST and GET are viable methods to query the resource in question (this header is similar to the Allow response header, but used strictly within the context of access control).

서버는 Access-Control-Allow-Origin: http://foo.example 라고 응답하면서 요청하는 출처에 대한 접근을 제한하고 있다. 또한 접근제어 허용메소드도 응답하는데, 이는 POST와 GET으로 자원을 조회할 수 있는 workable 메소드다. (이 헤더는 허가 응답 헤더와 비슷하지만, 접근 제어의 문맥안에서 제한적으로 사용되고 있음)

The server also sends Access-Control-Allow-Headers with a value of "X-PINGOTHER, Content-Type", confirming that these are permitted headers to be used with the actual request. Like Access-Control-Allow-Methods, Access-Control-Allow-Headers is a comma separated list of acceptable headers.

서버는 또한 Access-Control-Allow-Headers를 "X-PINGOTHER, Content-Type"의 값으로 전송함으로써, 실제 요청과 함께 사용될 수 있음을 확인하고 있다. Access-Control-Allow-Methods처럼, Access-Control-Allow-Headers도 허용가능한 헤더의 콤마로 구분된 리스트이다.

Finally, Access-Control-Max-Age gives the value in seconds for how long the response to the preflight request can be cached for without sending another preflight request. In this case, 86400 seconds is 24 hours. Note that each browser has a maximum internal value that takes precedence when the Access-Control-Max-Age is greater.

마지막으로 Access-Control-Max-Age는 초단위의 값을 제공하며, 얼마나 오랫동안 preflight에 대한 응답이 또다른 preflight요청 없이 기억될 수 있는지를 나타낸다. 이 경우에는 24시간이다. 각 브라우저는 Access-Control-Max-Age 값이 더 클 때 우선순위가 높다.

Preflight 각 요소에 대한 설명임.

아래는 실제 요청과 응답


Requests with credentials

<<여기는 한국어로 번역된 MDN을 참고하자..>>


Finiamo

CORS를 할 때 강의 들을 시간이 너무 없어가지고 대충 들었더니, 잘 이해가 안갔다. 그래서 MDN을 다시 번역하면서 대충 컨텍스트라도 알고 싶었음.

예전엔 위 그림처럼 서버가 클라이언트를 가지고 있었기 때문에 필요 없었지만, 이제는 싱글 페이지 애플리케이션 기술이 등장과 고도화에 따라, API를 이용한 리소스 활용이 필요해졌고, 이에 따라 CORS가 등장했다. 원래는 브라우저들이 Cross-Origin 요청을 제한했으나, 개발자들의 요청으로 지금은 허용된 범위(Allow)에서는 CORS가 가능해짐.

다시 말하자면, CORS는 추가 HTTP헤더를 사용하여 한 출처에서 실행중인 웹앱이 다른 출처의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이고, OPTIONS는 서버에서 allow하는 조건을 다 가지고 있는가를 확인하는 요청(preflight)정도로 정리 할 수 있을 것 같다.

어렵고, 심지어 익숙해질 시간조차 없는 것 같다. 하루가 엄청 빠르게 흘러가고, 이렇게라도 안하면 다 까먹을 것만 같아서 적는 블로그.

벌써 다 까먹고 있는 것 같다.. 오죽하면 소크라티브를 정리하고 있다...흑흑ㅠㅠ
그래도 잘 할 수 있다. 잘해보쟈 잘하자. 진짜 끝

profile
always 2B#

0개의 댓글