■ CORS - Cross Origin Resource Sharing
CORS란 개념에 대해 정리하겠습니다.
● CORS란?
CORS란 Cross Origin Resource Sharing의 줄임말로, Cross-Site Http Request를 가능하게
하는 표준 규약입니다.
다른 도메인으로부터 리소스가 필요할 경우 cross-site http request가 필요합니다.
기존에는 XMLHttpRequest는 보안상의 이유로 자신과 동일한 도메인으로만 HTTP요청을 보내도록
제한하였습니다. 즉 cross-origin http 요청을 제한하였죠
하지만 지속적으로 웹 애플리케이션을 개선하고 쉽게 개발하기 위해서는 이러한 request가
꼭 필요했습니다. 그래서 XMLHttpRequest가 cross-domain을 요청할 수 있도록하는 방법이
필요하게 되었죠. 이러한 요청을 바탕으로 CORS가 탄생하였습니다.
● CORS의 종류
크게 4종류로 나누어 볼 수 있습니다. 4가지 종류는 아래와 같습니다.
- Simple Request
- Preflight Request
- Credential Request
- Non-Credential Request
개념 및 예제 Request/Response를 통해 정리해보도록 할게요.
- Simple Request
먼저 기본적인 Simple Request입니다. 이는 다음 3가지를 만족해야 해요
1. GET, HEAD, POST 중 한 가지 방식을 사용
2. POST일 경우 Content-type이 아래 셋 중 하나를 만족
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
3. 커스텀 헤더를 전송하지 않아야 함
Simple Request는 매우 간단한 형태로 요청되고 응답됩니다.
그 형태는 아래와 같습니다. (파란 블록이 Request / 노란 블록이 Response)
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 |
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2.0.61 Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml |
위의 요청 및 응답에 대해 설명하겠습니다.
파란 블록의 HTTP Request는 foo.example로 부터 온 요청입니다.
노란 블록의 HTTP Response는 bar.other로 부터 온 응답입니다.
중간의 Access-Control-Allow-Origin: *이 보이시나요?
이는 bar.other이 cross-site 방식 내 모든 도메인으로부터 접근이 가능하다는 뜻입니다.
만약 요청한 페이지인 foo.example만을 포함했다면 아마 아래와 같이 표기되었겠죠?
Access-Control-Allow-Origin: foo.example
- Preflight Request
두 번째는 Preflight Request입니다.
이름에서 볼 수 있는 것 처럼 Preflight(예비) 요청을 먼저 보내고 서버가 이에
응답이 가능한 지 확인합니다. 예비 요청은 OPTION메소드로 HTTP요청을 전송합니다.
이후 실제 Actual(본) 요청을 보냅니다.
그리고 서버가 이에 응답하며 통신하는 형태이죠.
Preflight Request는 위의 Simple Request에 해당하는 조건에 만족하면 안되요.
그렇기에 GET, HEAD, POST 이외 메소드를 사용하는 경우에만 사용 가능한 요청입니다
만약 POST 요청을 사용할 경우에는 Content Type이 위의 3가지 경우가 아니거나
또는 커스텀 헤더를 사용할 경우에 사용할 수 있다는 점을 기억해야 합니다.
예비 요청과 예비 응답, 본 요청과 본 응답 총 4번의 형태로 구성되어 있습니다.
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 |
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER Access-Control-Max-Age: 1728000 Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain |
먼저 예비 요청 및 응답에 대해서 볼까요
위에 말한 것 처럼 OPTION 메소드를 이용하여 예비 요청을 보냈습니다.
Access-Control-Request-Method: POST는 이후 본 요청에서 POST 메소드가
전달 될 것을 미리 알려주는 역할을 합니다.
Access-Control-Request-Headers: X-PINGOTHER는 본 요청에서 전달될 헤더 정보를
포함하고 있는데요. X-PINGOTHER이라는 커스텀 헤더가 전송될 예정입니다.
이후 이 예비 요청에 대한 응답이 위의 노란 블록처럼 전해집니다.
자세히 살펴봐야 할 것은 아래의 3줄입니다.
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
셋 모두 Access-Control-Allow-* 이렇게 시작합니다.
당연히 허가된 정보를 뜻하는 것이지요.
이후에는 위의 Simple Request와 같이 본 요청과 응답이 수행됩니다.
- Credential
세 번째는 HTTP Cookie와 HTTP Authentication 정보를 인식할 수 있게 해주는 요청입니다
요청 시 xhr.withCredentials = true를 지정하는 것이 가장 큰 특징입니다.
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 |
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:34:52 GMT Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2 X-Powered-By: PHP/5.2.6 Access-Control-Allow-Origin: http://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: true
만약 위의 설정이 false라면? 브라우저는 이 요청을 거부할 것입니다.
거부 할 때는 거부되었다는 어떠한 메시지도 전달하지 않아요. Response가 없습니다.
- Non-Credential
마지막 요청은 Non-Credential 요청입니다.
사실 withCredentials 플래그는 디폴트 값이 false입니다.
그러니 위의 Credential 요청에서와 같이 처리해주지 않는다면 모든 요청이 바로
Non-Credential에 해당된다고 볼 수 있습니다.
4가지의 CORS에 대해 정리해 보았습니다. 직접 테스트하고 실제 메시지를 보면 도움이 되겠죠?
과연 정리한 것처럼 요청과 응답이 올까요? 직접 확인해 볼 수 있는 사이트를 소개해드립니다.
http://arunranga.com/examples/access-control/
접속 후 테스트를 해볼 수 있어요. 개발자 도구 켜는건 당연한거겠죠?
직접 개념이해 후 확인해보면 완전히 이해하실겁니다.
그럼 포스팅을 마치겠습니다. 감사합니다
'ETC' 카테고리의 다른 글
[HTML] 리스트 태그 (ul, ol, dl) (1) | 2017.10.06 |
---|---|
[Cron] 크론(cron) 표현식 정리 (2) | 2017.07.26 |
[CDATA] CDATA란 (0) | 2017.07.01 |
[비트코인과 랜섬웨어] 그 상관관계 ? (0) | 2017.05.07 |
[BOOTSTRAP] 그리드 시스템 (Grid System) (0) | 2017.03.12 |