CORS란?
교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. - MDN
URL 구조
프로토콜의 HTTP는 80번, HTTPS는 443번 포트를 사용하는데, 80번과 443 포트는 생략 가능하다.
출처(Origin)란?
출처(Origin)란 URL 구조에서 살펴본 Protocal, Host, Port를 합친 것을 말합니다. 브라우저 개발자 도구의 콘솔 창에 location.origin를 실행하면 출처를 확인할 수 있다.
같은 출처 VS 다른 출처
같은 출처인지 다른 출처인지 이해를 돕기 위해 예제를 하나 살펴보도록 하겠습니다. 현재 웹페이지의 주소가 https://huitopia.github.io/tech/때 같은 출처인지 다른 출처인지 아래 테이블과 같은 결과를 얻을 수 있습니다.
URL | 결과 | 이유 |
https://huitopia.github.io/about | 같은 출처 | Protocal, Host, Port 동일 |
https://huitopia.github.io/about?q=work | 같은 출처 | Protocal, Host, Port 동일 |
https://huitopia.github.io/about#work | 같은 출처 | Protocal, Host, Port 동일 |
https://huitopia.github.io | 다른 출처 | Protocal 다름 |
https://huitopia.github.io:81 | 다른 출처 | Port 다름 |
https://huitopia.nani.com | 다른 출처 | Host 다름 |
동일 출처 정책(Same-Origin Policy)이란?
같은 출처에서만 리소스를 공유할 수 있다는 규칙이다. 브라우저에서 다른 서버에서 요청할 경우에 해당되고, 브라우저를 거치지 않고 서버 간 통신을 할 때는 이 정책이 적용되지 않는다.
이런 정책이 왜 존재할까? 만약 다른 출처의 어플리케이션이 서로 통신하는 것에 대해 아무런 제약도 존재하지 않는다면 악의를 가진 사용자가 소스 코드를 보고 CSRF(Cross-Site Request Forgery) 나 XSS(Cross-Site Scripting) 와 같은 방법을 사용하여 정보를 탈취할 수 있다.
CORS는 다른 출처의 리소스가 필요한 경우, SOP를 우회하기 위한 여러가지 방법 중 가장 권장되는 방법이다.
동일 출처 정책의 장점
동일 출처 정책을 지키면 외부 리소스를 가져오지 못해 불편하지만, 동일 출처 정책은 XSS나 XSRF 등의 보안 취약점을 노린 공격을 방어할 수 있습니다. 하지만 현실적으로는 외부 리소스를 참고하는 것은 필요하기 때문에 외부 리소스를 가져올 수 있는 방법이 존재해야 합니다. 외부 리소스를 사용하기 위한 SOP의 예외 조항이 CORS입니다.
CORS 동작원리
Simple request
단순 요청 방법은 서버에게 바로 요청을 보내는 방법이다.
단순 요청은 서버에 API를 요청하고, 서버는 Access-Control-Allow-Origin 헤더를 포함한 응답을 브라우저에 보냅니다. 브라우저는 Access-Control-Allow-Origin 헤더를 확인해서 CORS 동작을 수행할지 판단한다.
Simple request 조건
서버로 전달하는 요청(request)이 아래의 3가지 조건을 만족해야 서버로 전달하는 요청이 단순 요청으로 동작합니다.
- 요청 메서드(method)는 GET, HEAD, POST 중 하나여야 합니다.
- Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 헤더를 사용하면 안 됩니다.
- Content-Type 헤더는 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나를 사용해야 합니다.
첫 번째 조건은 어렵지 않은 조건이지만 2번, 3번 조건은 까다로운 조건입니다. 2번 조건은 사용자 인증에 사용되는 Authorization 헤더도 포함되지 않아 까다로운 조건이며, 3번 조건은 많은 REST API들이 Content-Type으로 application/json을 사용하기 때문에 지켜지기 어려운 조건입니다.
Preflight request
Preflight 요청은 서버에 예비 요청을 보내서 안전한지 판단한 후 본 요청을 보내는 방법입니다.
GET, POST, PUT, DELETE 등의 메서드로 API를 요청했는데, 크롬 개발자 도구의 네트워크 탭에 OPTIONS 메서드로 요청이 보내지는 것을 보신 적 있으시다면 CORS를 경험하셨던 것입니다. Preflight 요청은 실제 리소스를 요청하기 전에 OPTIONS라는 메서드를 통해 실제 요청을 전송할지 판단합니다.
OPTIONS 메서드로 서버에 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 Access-Control-Allow-Origin 헤더를 포함한 응답을 브라우저에 보냅니다. 브라우저는 단순 요청과 동일하게 Access-Control-Allow-Origin 헤더를 확인해서 CORS 동작을 수행할지 판단합니다.
참고링크
'IT > etc.' 카테고리의 다른 글
Protocol, HTTP? (0) | 2022.11.21 |
---|---|
인터넷의 작동 원리(인터넷, 라우터, 모뎀, IP) (0) | 2022.11.21 |
[VScode] Prettier 적용 (0) | 2022.05.23 |
[Git] Commit Message Convention (0) | 2022.05.12 |
WebSocketAPI (0) | 2021.12.25 |