CORS

2020. 3. 29. 17:47네트워크, 통신

CORS란

CORS의 개념

CORS(Cross Origin Resource Sharing)은 추가적은 HTTP Header를 사용해서 애플리케이션이 다른 도메인의 리소스에 접근할 수 있도록 하는 메커니즘입니다.

CORS가 필요한 이유

일반적으로 HTTP 요청은 기본적으로 Cross-Stie Http Request가 가능합니다. 다시 말하면 다른 도메인의 이미지 파일을 가져오거나 다른 도메인의 스크립트를 가져오거나 하는 것이 모두 가능합니다. 하지만 스크립트에서 생성된 Cross-Site HTTP Request는 Same Origin Policy를 적용 받기 때문에 Cross-Site Http Request가 불가능합니다.

최근 웹사이트들은 프론트 레이어와 백엔드 레이어를 분리해서 프론트와 백엔드를 API로 묶는 방식을 많이 사용합니다. 따라서 사용자가 프론트에 처음 접속하고 데이터를 백엔드에서 가져오기 위해서는 백엔드 서버에 CORS 설정이 필요하게 됩니다.

CORS의 동작 원리

브라우저가 리소스를 요청할 때 추가적인 헤더에 정보를 담습니다. 내 origin은 무엇이고 어떤 메소드를 사용해서 요청을 할 것이고 어떤 헤드들을 포함할 것인지를 담아서 서버에 전송합니다. 서버는 서버가 응답할 수 있는 origin들을 헤더에 담아서 브라우저에게 보냅니다. 브라우저가 헤더를 보고 해당 origin에서 요청할 수 있다면 리소스 전송을 허용하고 만약 불가능하다면 에러를 발생시킵니다.

CORS의 종류

Simple Reuqest
아래의 3가지 조건을 모두 만족하면 Simple Request입니다.

  • GET, HEAD, POST 중 한 가지의 방식을 사용
  • POST 방식일 경우 application/x-www-form-urlencoded, multipart/form-data, text/plain 이 중 하나가 Content-type이어야 함
  • 커스텀 헤더를 전송하지 말아야 함
GET /resources/public-data/ HTTP/1.1

Host: bar.other

User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1. 9.1b3pre) Gecko/20081130 Minefield/3.1b3pre

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

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

Connection: keep-alive

Referer: http://foo.example/examples/access-control/simpleXSInvocation.html

Origin: http://foo.example

Preflight Request
Simple Request 조건에 해당하지 않으면 브라우저는 Preflight Request 방식으로 요청합니다. Preflight Request는 GET, HEAD, POST 외의 다른 방식으로도 요청을 보낼 수 있고 다른 Content-type으로도 요청을 보낼 수도 있으며, 커스텀 헤더도 사용할 수 있습니다.
Preflight Request는 예비 요청과 본 요청으로 나뉘어 전송됩니다. 먼저 서버에 예비 요청을 보내고 서버는 예비 요청에 대해 응답하고, 그 다음에 본 요청을 서버에 보내고 서버도 본 요청에 응답합니다. 하지만, 예비 요청과 본 요청에 대한 서버단의 응답을 프로그래머가 프로그램 내에서 구분하여 처리하는 것은 아닙니다. 프로그래머가 Access-Control- 계열의 Response Header만 적절히 정해주면, OPTIONS 요청으로 오는 예비 요청과 GET, POST, HEAD 등으로 오는 본 요청의 처리는 서버가 알아서 처리합니다.

-- 예비 요청

OPTIONS /resources/post-here/ HTTP/1.1

Host: bar.other

User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre

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

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

Connection: keep-alive

Origin: http://foo.example

Access-Control-Request-Method: POST

Access-Control-Request-Headers: X-PINGOTHER


-- 본 요청

GET /resources/access-control-with-credentials/ HTTP/1.1

Host: bar.other

User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre

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

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

Connection: keep-alive

Referer: http://foo.example/examples/credential.html

Origin: http://foo.example

Cookie: pageAccess=2

Request with Credential
Http Cookie와 Http Authentication 정보를 인식할 수 있게 해주는 요청입니다. 요청시 xhr.withCredentials = ture를 지정해서 Credential 요청을 보낼 수 있고, Response Header에 반드시 Access-Control-Allow-Credentials: true를 포함해야 합니다. 그리고 Access-Control-Allow-Origin 헤더의 값에는 * 가 오면 안 되고 구체적인 도메인이 와야합니다.

Reuqest without Credential
CORS 요청은 기본적으로 Non-Credential 요청이므로, xhr.withCredentials=true를 지정하지 않으면 Non-Credential 요청입니다.

728x90

'네트워크, 통신' 카테고리의 다른 글

HTTP2  (0) 2020.06.09
SSL  (0) 2020.06.08
Https  (0) 2020.06.08
AMQP  (0) 2020.05.13
로드 밸런서  (0) 2020.03.20