CORS는 Cross-Origin Resource Sharing의 약자로 추가 HTTP 헤더를 사용하여 브라우저의 현재 웹페이지가 이 페이지를 받은 서버가 아닌 다른 서버의 자원을 호출할 수 있도록 액세스 권한을 부여하는 메커니즘이다.
HTTP는 기본적으로 Cross-Site HTTP Request가 가능하다. img 태그나 link 태그로 이미지를 가져온다던지 하는 것이 그 예이다.
하지만 누군가가 이를 악의적인 목적으로 사용할 경우 (ex. XSS) 문제가 발생할 수 있다.
그래서 웹 브라우저는 보안상의 문제로 기본적으로 특정도메인에서 다른 도메인으로 접근하는 Cross-Site HTTP Request를 제한하고 자신과 동일한 도메인으로만 HTTP 요청을 보내도록 제한했는데 이것을 Same Origin Policy (동일 출처 정책) 이라고 한다.
실제로 악의적인 목적이 아닌 어떤 기능을 구현할 때 다른 도메인에 접근해야할 경우가 있다. 하지만 이러한 경우에도 Same Origin Policy를 위반하게되어 브라우저에서는 이를 불허한다.
이러한 문제를 해결하기위해 CORS가 탄생하게 되었다.
CORS 요청과 종류
CORS 요청에는 다음의 4가지 종류가 있다.
- Simple Request
- Preflight Request
- Credential Request
- Non-Credential Request
Simple Request
Simple Request는 일반적인 요청이다. 다음의 조건에 만족되면 일반적인 요청으로 간주되고 일반적으로 서버와 통신을 할 수 있다.
- GET, HEAD, POST 중 한가지 방식을 사용해야함
- POST 방식일 경우, Content-type이 다음 셋 중 하나여야함.
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 커스텀 헤더를 전송하지 말아야함.
Preflight Request
일반적인 요청의 조건에 해당하지 않으면 브라우저는 Preflight Request 방식으로 요청을 보내게 된다. 이름에서 알 수 있듯이, 예비 요청을 먼저 보내고 서버에서 응답이 가능한지 확인 후, 가능하면 본 요청(원래 보내려던 요청)을 보내는 것이다.
OPTIONS method로 요청을 보내게되고, 서버에서는 이 요청을 받고 응답으로 Response Header에 서버가 허용할 옵션을 브라우저로 전달하게 된다. 브라우저에서는 서버가 보낸 Response 정보를 이용해서, 허용되지 않는 요청일 경우에는 405 에러를 발생시키고, 본 요청은 전송하지 않는다. 만약 허용된 요청일 경우에는 본 요청을 다시 보내서 의도한대로 기능한다.
CORS와 관련된 Response header로는 다음과 같은 것이 있다.
- Access-Control-Allow-Origin : 도메인을 지정하여 지정된 도메인으로부터 요청만 서버의 리소스에 접근할 수 있게한다.
- Access-Control-Allow-Methods : 요청을 허용하는 메소드를 지정 (기본값은 GET, POST)
- Access-Control-Allow-Headers : 요청을 허용하는 HTTP header를 지정한다.
- Access-Control-Allow-Credentials : Credential Request 방식이 사용될 수 있는지 지정
- Access-Control-Allow-Max-Age : 클라이언트에서 예비 요청의 결과를 저장하고 있을 시간을 지정한다. 해당 시간 동안 요청을 다시 보내지 않는다.
참고로 예비 요청(OPTIONS)과 본 요청(ex. POST)을 서버단에서 직접 처리 로직을 구분하여 구현하지 않고, OPTIONS 요청에 대한Response Header만 적절히 지정해주면 본 요청은 서버에서 알아서 처리한다.
Credential Request
HTTP Cookie와 Authentication 정보를 인식할 수 있게 해주는 요청이다.
기본적으로 모든 요청은 withCredentials 옵션이 false로 되어 있어 쿠키나 Authentication 정보를 보내지 않기 때문에 요청 시에 withCredentials 옵션을 true로 설정해주어야 한다.
하지만 이것만 해주어선 CORS 요청이 거부된다.
위에서 Access-Control-Allow-Credentials 옵션을 true로 설정해주어야 하고, Access-Control-Allow-Origin에 * (모든 도메인 허용) 이 아닌 특정 도메인으로 지정해주어야 한다.
Non-Credential Request
기본적으로 CORS 요청은 위에서 말한 것처럼 withCredentials이 false인 요청이다. 그래서 credential 요청이 아닌 경우 Non-Credential 요청이라고 할 수 있다.
cors에 대한 기본적인 개념과 왜 발생하는지, 어떻게 해결할 수 있는지 알 수 있었다.
클라이언트와 서버 코드를 각각 작성 후 연동시키고 클라이언트에서 서버로 요청을 보냈을 때 처음 만났던 에러이다. 클라이언트와 서버가 분리되어 있기 때문에 cross 도메인으로 간주되어 CORS 에러가 발생한 것이다.
서버의 경우, express의 cors 미들웨어를 사용해서 cors 설정을 수월하게 할 수 있었다. cors 미들웨어에도 많은 옵션과 설정이 있었는데, 나중에 시간이 나면 좀 더 공부해보면 좋을 것 같다.
아래는 참고한 레퍼런스 입니다.
https://bigzero37.tistory.com/60
https://brownbears.tistory.com/336
https://zamezzz.tistory.com/137
https://brunch.co.kr/@adrenalinee31/1
https://homoefficio.github.io/2015/07/21/Cross-Origin-Resource-Sharing/
'HTTP' 카테고리의 다른 글
(191222) Headers (0) | 2019.12.22 |
---|---|
(191215) AJAX (0) | 2019.12.15 |
(191208) HTTP Method, Status code (0) | 2019.12.08 |
(191208) HTTP (0) | 2019.12.08 |
댓글