CORS 탄생 배경
웹 사이트 개발 시, 중요한 이유 중의 하나는 크로스 도메인(Cross Domain)이다.
HTTP 요청은 기본적으로 Cross-site HTTP Requests가 가능하다.
즉, <img>태그로 다른 도메인의 이미지 파일을 가져오거나, <link>태그로 다른 도메인의 CSS를 가져오는 것이 가능하다.
하지만 <script>로 둘러싸여 있는 스크립트에서 생성된 Cross-Site HTTP Requests는 Same Origin Policy를 적용 받기 때문에 Cross-Site HTTP Requests가 불가능하다.
즉, Cross-Site Http Requests는 프로토콜, 호스트, 포트 가 같아야지 요청이 가능하다. 더 쉽게 말하면 웹페이지의 스크립트는 그 페이지와 같은 서버에 있는 주소로만 AJAX 요청이 가능하다.
시간이 흘러 AJAX가 널리 사용되면서 <script>태그로 둘러싸여 있는 스크립트에서 생성되는 XMLHttpRequest에 대해서도 Cross-Site HTTP Requests가 가능해야 한다는 요구가 늘어나면서 W3C에서 CORS라는 이름의 권고안이 나오게 되었다.
CORS(Cross-origin resource sharing)
1. CORS(Cross-origin resource sharing)정의
Cross-Site HTTP Requests를 가능하게 하는 표준 규약이다. 외부 도메인 서버와 통신하기 위한 방식을 표준화했는데, 서버와 클라이언트가 헤더의 규칙으로 요청이나 응답을 어떻게 반응할지 결정한다.
2. CORS 요청 방식
* CORS 요청은 Simple/Preflight, Credential/Non-Credential의 조합으로 4가지가 존재한다.
가. SImple Request
1) GET, HEAD, POST 중의 한가지 방식을 사용해야 한다.
2) POST 방식일 경우 Content-type이 아래 셋 중의 하나여야 한다.
가) application/x-www-form-urlencoded
나) multipart/form-data
다) text/plain
3) 커스텀 헤더를 전송하지 말아야 한다.
4) 서버에 1번 요청하고, 서버도 1번 회신하는 것으로 처리가 종료된다.
나. Preflight Request
1) Simple Request 방식과 전혀 반대의 방식이다.
2) GET, HEAD, POST 외의 다른 방식으로 요청을 보낼 수 있다.
3) application/xml 처럼 다른 Content-type으로 요청을 보낼 수 있다.
4) 커스텀 헤더를 사용할 수 있다.
5) 서버에 예비 요청과 본 요청으로 나뉘어 전송한다.
다. Request with Credential
1) HTTP Cookie와 HTTP Authentication 정보를 인식할 수 있게 해주는 요청이다.
2) 클라이언트에서 요청시 xhr.withCredentails = true를 지정해서 Credential 요청을 보내야 한다.
3) 서버는 반드시 Response Header에 Access-Control-Allow-Credentials: true를 포함해야 한다.
4) 또한 Access-Control-Allow-Origin 헤더의 값에는 http://*과 같은 구체적인 도메인이 와야 한다.
라. Request without Credential
1) CORS 요청은 기본적으로 Non-Credential 요청이므로, xhr.withCredentials = true 를 지정하지 않으면 Non-Credential 요청이다.
3. HTTP Response Headers (CORS 관련)
* 서버에서 지정하는 헤더이다.
가. Access-Control-Allow-Origin
1) Access-Control-Allow-Origin 헤더의 값으로 지정된 도메인으로부터의 요청만 서버의 리소스에 접근할 수 있게 한다.
2) 모든 도메인으로부터의 서버 리소스 접근을 허용하려면 * 를 지정한다. (Request with Credential 제외)
나. Access-Control-Expose-Headers
1) 기본적으로 브라우저에게 노출이 되지 않지만, 브라우저 측에서 접근할 수 있게 허용해주는 헤더를 지정할 수 있다.
2) 기본적으로 노출이 되는 헤더는 다음과 같다.
가) Cache-Control
나) Content-Language
다) Content-Type
라) Expires
마) Last-Modified
바) Pragma
3) Access-Control-Expose-Headers를 지정하게 되면 브라우저 측에서 커스텀 헤더를 포함하여, Content-Length 헤더 정보도 알 수 있게 된다.
다. Access-Control-Max-Age
1) PreFlight Request의 결과가 캐시에 얼마나 오랫동안 남아있는지를 나타낸다.
라. Access-Control-Allow-Credentials
1) Request with Credential 방식이 사용될 수 있는지를 지정한다.
2) PreFlight Request의 예비 요청에 대한 응답으로 Access-Control-Allow-Credentials:false를 포함하면, 본 요청에서 Request with Credential 방식을 요청할 수 없다.
마. Access-Control-Allow-Methods
1) PreFlight Request의 예비 요청에 대한 Response Header에 사용되며, 서버의 리소스에 접근할 수 있는 HTTP Method 방식을 지정한다.
바. Access-Control-Allow-Headers
1) PreFlight Request의 예비 요청에 대한 Response Header에 사용되며, 본 요청에서 사용할 수 있는 HTTP Header를 지정한다.
4. HTTP Request Headers (CORS 관련)
* 클라이언트에서 지정하는 헤더이며, 브라우저가 자동으로 지정한다.
가. Origin
1) Cross-site 요청을 날리는 요청 도메인 URI를 나타내며, Access-Control... 이 적용되는 모든 요청에는 반드시 포함된다.
2) Origin 에서는 서버 이름(포트 포함)만 포함되며 경로 정보는 포함되지 않는다.
나. Access-Control-Request-Method
1) PreFlight Request의 예비 요청에 대한 RequestHeader에 사용되며, 본 요청에서 어떤 HTTP Method를 사용할 지 서버에게 알려준다.
다. Access-Control-Request-Header
1) PreFlight Request의 예비 요청에 대한 RequestHeader에 사용되며, 본 요청에서 어떤 HTTP Header를 사용할 지 서버에게 알려준다.
정리
- CORS를 쓰면 AJAX로도 Same Origin Policy 제약을 넘어 다른 도메인(서브 도메인 포함)의 자원을 사용할 수 있다.
- CORS를 사용하기 위해서는 2가지 조건이 충족되야한다.
1. 클라이언트에서 Access-Control 로 시작하는 부분을 HTTP Header에 포함시켜야 전송해야한다.
2. 서버에서는 Access-Control 로 시작하는 부분을 HTTP Header에 포함하여 회신하여야 한다.
'기타' 카테고리의 다른 글
TCP - 3way handshake & 4way handshake (0) | 2020.01.04 |
---|---|
XSS, CSRF (0) | 2020.01.04 |
데브옵스(DevOps) (0) | 2020.01.02 |
TDD(Test Driven Development) (0) | 2020.01.02 |
객체지향 프로그래밍 (0) | 2019.12.31 |