[Today I Learned] CORS란?

이정환·2020년 3월 21일
0

CORS(Cross Origin Resource Sharing)란?

cors는 추가 HTTP 헤더를 사용하여 한 출저 or 도메인에서 다른 출저 or 도메인의 리소스를 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제

브라우저는 보안상의 이유로, 스크립트의 CORS HTTP 요청을 제한
XMLHTTPRequest or Fetch API는 동일 출저 정책을 따라 다른 출저의 응답을 받기 위해서는 CORS 헤더를 포함한 응답을 받아야함

CORS 종류

CORS의 종류는 다음과 같다.

  • simple requests
  • preflight requests
  • credential requests
  • non-credential requests

1. simple requests

1) GET, POST, HEAD Method 중 하나를 사용
2) Content-type은 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나를 사용
3) 커스텀 Header 사용 X

스크립트에서 호출 예제)

const xhr = new XMLHttpRequest();
const url = 'https://bar.other/resources/public-data/';
xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();

호출 요청

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하세요

호출 응답

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

서버의 응답 중 Accss-Control-Allow-Origin은 모든 출저 or 도메인에서 접근이 가능하다는 것을 의미
특정 출저 또는 도메인만 접근을 허용하려면 Access-Control-Allow-Origin: https://www.wehago.com을 반환

2. preflight requests

예비요청을 서버측으로 전송하여 서버가 전송가능한지에 대한 예비응답을 받아 본 요청을 하는 요청방식이며 예비요청, 예비응답, 본요청, 본응답으로 구성
예비요청 시 OPTIONS 메소드를 사용하여 요청

스크립트에서 호출예제 )

const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://bar.other/resources/post-here/');
xhr.setRequestHeader('Ping-Other', 'pingpong');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');

호출 요청

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

simple requests와 달리 Access-Control-Request-Method와 Access-Control-Request-Headers가 추가되었는데
Access-Control-Request-Method는 본요청에서 사용할 HTTP 메소드를 정의하며 Access-Control-Request-Headers는 본요청에서 사용할 커스텀 Header가 무엇인지 정의
서버의 응답에서 Access-Control-Allow-* 를 응답하며 리소스 접근에 관하여 허가했다는 의미를 뜻한다.

3. credential

HTTP Cookie와 Authentication 정보를 인식할 수 있는 요청방식

스크립트 호출예제)

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값을 통해 설정

호출요청

GET /resources/access-control-with-credentials/ 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
Referer: http://foo.example/examples/credential.html
Origin: http://foo.example
Cookie: pageAccess=2

호출응답

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

서버의 응답에서 Access-Control-Allow-Credentials 값이 false 일경우 브라우저는 해당 요청을 거부

4. non-credential requests

invocation.withCredentials는 디폴트가 false이므로 withCredentials를 설정하지 않은 모든 요청은 non-credential requests

출저

0개의 댓글