CORS

Tacocat·2022년 2월 13일
0

Javascript

목록 보기
4/4

CORS의 정의

교차 출처 리소스 공유(Cross-origin resource sharing, CORS), 교차 출처 자원 공유는 웹 페이지 상의 제한된 리소스를 최초 자원이 서비스된 도메인 밖의 다른 도메인으로부터 요청할 수 있게 허용하는 구조이다. 웹페이지는 교차 출처 이미지, 스타일시트, 스크립트, iframe, 동영상을 자유로이 임베드할 수 있다. 특정한 도메인 간(cross-domain) 요청, 특히 Ajax 요청은 동일-출처 보안 정책에 의해 기본적으로 금지된다.

출처: https://ko.wikipedia.org/wiki/%EA%B5%90%EC%B0%A8_%EC%B6%9C%EC%B2%98_%EB%A6%AC%EC%86%8C%EC%8A%A4_%EA%B3%B5%EC%9C%A0 (교차 출처 리소스 공유)

즉, 도메인이 다른 곳에서 온 요청은 기본적으로 허용되지 않지만, 서버에 특정 도메인(혹은 전부)에서 온 요청은 허용하는 목록을 만들어 두고, 요청한 도메인에서는 CORS HTTP헤더라는 허가 증명서를 제출해 서버의 목록과 대조하고 확인되면 요청이 통과하게끔 만들어주는 구조이다.

예시

MDN에서는 다음과 같은 예를 제시하고 있다.

출처 측

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example

Origin:
요청을 보낸 출처

서버 측

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: https://foo.example
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[…XML Data…]

Access-Control-Allow-Origin: *
만약 서버에서 이와 같이 설정되어 있다면, 외부 모든 도메인에서 온 요청을 허용한다는 의미이다.
Access-Control-Allow-Origin: https://foo.example
이렇게 설정된 경우에는 https://foo.example에서 온 요청만을 허용하겠다는 의미이다.

프리플라이트 요청(preflighted request)

프리플라이트 요청은, 먼저 OPTIONS 메서드를 통해 다른 도메인의 리소스로 HTTP 요청을 보내 실제 요청이 전송하기에 안전한지 확인한다. 요청이 안전한 것이 확인되면 실제 요청을 보내게 된다. 만약 안전하지 않다면 실제 요청은 보내지지 않는다. 이렇게 하는 이유는 cross-origin 요청은 데이터에 영향을 줄 수 있기 때문이다.

예시

MDN에서는 다음과 같은 예를 제시하고 있다.

프리플라이트 요청

OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type


HTTP/1.1 204 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive

Access-Control-Request-Method:
실제 요청을 전송할 때 이와 같은 방식으로 요청을 전송하겠다는 것을 알려준다.
Access-Control-Request-Headers:
실제 요청을 전송할 때 해당 항목의 사용자 정의 헤더와 함께 전송된다는 것을 알려준다.


Access-Control-Allow-Methods:
서버에서 해당하는 리소스를 쿼리하는데 이와 같은 방식이 유용하다는 것을 알려준다
Access-Control-Allow-Headers:
실제 요청에 헤더를 사용할 수 있음을 알려준다.
Access-Control-Max-Age:
응답 캐싱 시간, 한 번의 프리플라이트 요청이 성공적으로 실행된 뒤, 설정된 시간 동안 이후 요청에서 프라플라이트 요청을 건너 뛰고 실제 요청만을 수행한다. 디폴트 값은 5초

관련 정보:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age

실제 요청

POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: https://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: https://foo.example
Pragma: no-cache
Cache-Control: no-cache

<person><name>Arun</name></person>


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some GZIP'd payload]

심플 리퀘스트 (Simple requests)

일부 요청들은 프리플라이트 요청을 필요로 하지 않는다. 이런 요청에 해당하기 위해서는 다음의 항목들을 모두 충족시켜야 한다.

다음 중 하나의 메서드

  • GET
  • POST
  • HEAD

유저 에이전트가 자동으로 설정한 헤더

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type

Content-Type은 다음과 같은 값들만 허용된다

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

인증정보를 포함한 요청 (credentialed requests)

credentialed requests는 HTTP cookies 와 HTTP Authentication 정보를 인식한다.

예시
MDN에서는 다음과 같은 예를 제시하고 있다.

const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/credentialed-content/';

function callOtherDomain() {
  if (invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    invocation.send();
  }
}

invocation.withCredentials:
해당 값이 true가 아니라면 호출된 웹 컨텐츠에 응답을 제공하지 않는다.

출처 및 참조: https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
(교차 출처 리소스 공유)

profile
개발자 꿈나무

0개의 댓글