본문 바로가기

CS

플랫폼 API 호출 시 발생하는 오류 CORS란 무엇인가?

Cross Origin Resource Sharing의 약자로 HTTP 프로토콜의 헤더를 사용하여 하나의 출저 or 도메인에서 다른 출저 or 도메인의 리소스에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제

브라우저의 보안상의 이유로 스크립트의 CORS HTTP 요청을 제한

 

Web API(XMLHttpRequest) or Fetch API는 동일 출저 정책에 따라 다른 출저 리소스를 접근하기 위해서는 CORS 헤더를 포함한 응답을 받아야합니다.

 

CORS 종류는 다음과 같습니다.

  • simple requests

  • preflight requests

  • credential reqeusts

  • non-credential reqeusts

1. simple requests 

  • GET, POST, HEAD Method 중 하나를 사용
  • Content-type은 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나를 사용
  • Custom 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

서버의 응답 중 Header의 Access-Control-Allow-Origin : * 모든 출저 or 도메인에서 접근이 가능하다는 것을 의미합니다.

특정 출저 or 도메인에서만 접근할 수 있도록 제한하려면 Access-Control-Allow-Origin : https://www.naver.com 

 

네이버

네이버 메인에서 다양한 정보와 유용한 컨텐츠를 만나 보세요

www.naver.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

 

예비 요청 중 Access-Control-Request-Method와 Access-Control-Request-Headers가 추가되었는데 Method는 본요청에서 사용될 HTTP 메소드를 정의하며 Headers는 본요청에서 사용될 커스텀 헤더가 무엇인지 정의합니다.

서버의 예비 응답에서 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

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

 

참조

'CS' 카테고리의 다른 글

SOAP에 대해서 알아보자  (0) 2020.12.02
XSS(Cross Site Scripting)란?  (0) 2020.12.02
HTTP에 대해서 알아보자  (0) 2020.11.30