CORS(Cross-Origin Resource Sharing)
직역하면 교차 출처 리소스 공유이다.
한 출처에 있는 자원에서 다른 출처에 있는 자원에 접근하도록 하는 개념
다른 출처에 있는 자원을 요청한다고 하면, 이를 교차 출처 요청이라고 부른다.
추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제. 웹 애플리케이션은 리소스가 자신의 출처와 다를 때 교차 출처 HTTP 요청을 실행한다.
- MDN
출처?
위 URL 구조에서 "Protocol, Host, Port" 3가지가 같으면 동일 출처(Origin)라고 한다.
(Port는 80, 443 이면 생략이 가능하다)
예를 들어 "https://skroy0513.tistory.com/40"과 같은 출처인지 다른 출처인지 알아보자
URL | 결과 | 이유 |
https://skroy0513.tistory.com/hello | 같은 출처 | Protocol, Host, Port 동일 |
https://skroy0513.tistory.com/manage?type=post | 같은 출처 | Protocol, Host, Port 동일 |
https://skroy0513.tistory.com/manage#name | 같은 출처 | Protocol, Host, Port 동일 |
http://skroy0513.tistory.com | 다른 출처 | Protocol 다름 |
https://skroy0513.tistory.com:81/manage | 다른 출처 | Port 다름 |
https://skroy0513.blog.com | 다른 출처 | Host 다름 |
다른 출처 요청일 경우, CORS 정책에 준수하여 요청해야만 정상적으로 응답을 받는다.
다른 출처 요청의 위험성
출처가 다른 두 개의 애플리케이션이 마음대로 소통할 수 있는 환경은 꽤 위험한 환경이다.
CORS가 없이 모든 곳에서 데이터를 요청할 수 있게 되면, 다른 사이트에서 원래 사이트를 흉내 낼 수 있게 된다.
예를 들어 기존 사이트와 완전히 동일하게 동작하도록 하여 사용자가 로그인을 하도록 만들고, 로그인했던 세션을 탈취하여 악의적으로 정보를 추출하거나 다른 사람의 정보를 입력하는 등 공격이 가능하다.
이런 공격을 할 수 없도록 브라우저에서 보호하고, 필요한 경우에만 서버와 협의하여 요청할 수 있도록 하기 위해서 필요하다
홈페이지를 서핑하다가 <script>가 심어진 evil.com을 방문했다고 가정해 보자. 해당 페이지를 방문했을 때 <script>가 실행되어 Ajax 호출로 bank.com에 "DELETE bank.com/account"를 요청해 계좌를 삭제할 수 있는 사고가 발생할 수 있다.
동일 출처 정책 (Same Origin Policy)
웹에는 크게 SOP(Same Origin Policy)와 CORS(Cross-Origin Resource Sharing) 두 가지 정책이 있다. SOP는 같은 출처에서만 리소스를 공유할 수 있다는 규칙을 가진 정책이다.
브라우저는 SOP를 지켜서 다른 출처의 리소스 접근을 금지하는데, 실제로 웹페이지는 상당히 자주 다른 출처의 리소스를 사용한다.
"skroy0513.tistory.com"이라는 도메인 주소를 사용하는 웹페이지에서 "skroy0513.naver.blog"라는 API 서버로 데이터를 요청해서 화면을 그린다면 이 웹페이지는 동일 출처 정책을 위반한 것이 된다.
장점
외부 리소스를 가져오지 못해 불편하지만, SOP는 XSS나 XSRF 등의 보안 취약점을 노린 공격을 방어할 수 있다.
하지만 현실적으로 외부 리소스를 참고하는 것은 필요하기 때문에 외부 리소스를 가져올 수 있는 방법이 존재해야 하는데,
그것이 CORS이다.
CORS 동작원리
단순 요청 방법(Simple request)과 예비 요청을 먼저 보내는 방법(Preflight request) 2가지가 있다.
Simple request
서버에게 바로 요청을 보내는 방법이다.
단순 요청은 서버에 API를 요청하고, 서버는 Access-Control-Allow-Origin 헤더를 포함한 응답을 브라우저에 보낸다.
브라우저는 Access-Control-Allow-Origin 헤더를 확인해서 CORS 동작을 수행할지 판단한다.
조건
서버로 전달하는 요청이 아래의 3가지 조건을 만족해야 서버로 전달하는 요청이 단순 요청으로 동작한다.
- 요청 메서드는 GET, HEAD, POST 중 하나여야 한다.
- Accept, Accept-Language, Content-Language, Conten-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 헤더를 사용하면 안 된다.
- Content-Type 헤더는 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나를 사용해야 한다.
2번 조건은 사용자 인증에 사용되는 Authorization 헤더가 포함되지 않고, 3번 조건은 많은 REST API들이 application/json을 사용하기 때문에 까다롭다
Preflight request
서버에 예비 요청을 보내서 안전한지 판단한 후 본 요청을 보내는 방법이다.
예비 요청에는 OPTIONS 메서드가 사용된다.
fetch API를 사용하여 브라우저에게 리소스를 받아오는 명령을 내리면 브라우저는 서버에게 예비 요청을 먼저 보낸다.
서버는 예비 요청 응답으로 현재 어떤 것을 허용하고, 어떤 것을 금지하고 있는지에 대한 정보를 응답 헤더에 담아서 브라우저에게 보내준다.
이후 브라우저는 자신이 보낸 예비 요청과 서버가 응답에 담아준 내용을 정책과 비교하여 안전하다고 판단되면 같은 엔드 포인트로 다시 본 요청을 보내게 된다.
그리고 서버가 본 요청에 대한 응답을 하면 브라우저는 최종적으로 응답 데이터를 자바스크립트에 넘겨준다.
CORS 에러 대응하기
서버에서 Access-Control-Allow-Origin 응답 헤더 세팅하기
서버에서 위 응답 헤더를 설정해서 요청을 수락할 출처를 명시적으로 지정할 수 있다.
이 헤더를 세팅하면 출처가 다르더라도 리소스 요청을 허용하게 된다.
Access-Control-Allow-Origin: *
*을 설정하게 되면 출처에 상관없이 리소스에 접근할 수 있는 와일드카드이기 때문에 보안에 취약해진다.
그래서 "Access-Control-Allow-Origin: https://skroy0513.naver.blog"와 와 같이 직접 허용할 출처를 세팅하는 방법이 좋다
실전
Q. CORS에 대한 설명을 부탁드릴게요
A. CORS는 출처가 다른 자원들을 공유한다는 뜻으로, 한 출처에 있는 자원에서 다른 출처에 있는 자원에 접근하도록 하는 개념입니다. 출처란 "Protocol, Host, Port" 3가지가 모두 같으면 동일 출처라고 합니다. CORS가 없이 모든 데이터를 요청할 수 있게 된다면, 은행 도메인에 들어가서 계좌를 삭제하는 <script> 파일이 심어진 악성 브라우저를 열람했을 때, 해당 <script> 파일이 ajax 요청을 통해 나의 계좌를 삭제하는 일이 발생할 수 있습니다.
CORS의 동작 방식에는 단순 요청 방법과 예비 요청을 먼저 보내는 방법 2가지가 있습니다. 단순 요청 방법은 HTTP의 메서드와, Header의 타입, Content-Type의 종류에 조건을 걸어 위 조건이 모두 만족하면 요청을 직접 받는 것을 말합니다. 예비 요청을 먼저 보내는 방법은 OPTIONS 메서드로 요청을 보내 안전한지 파악이 되면 본 요청을 보내고 자원을 받는 것을 말합니다.
참고
https://escapefromcoding.tistory.com/724#%EC%A0%84%EC%97%AD-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0
https://docs.tosspayments.com/resources/glossary/cors
항해 개발자 취업 리부트 코스를 수강하고 작성한 콘텐츠 입니다.
IT 커리어 성장 코스 항해99, 개발자 취업부터 현직자 코스까지
항해99는 실무에 집중합니다. 최단기간에 개발자로 취업하고, 현직자 코스로 폭발 성장을 이어가세요. 실전 프로젝트, 포트폴리오 멘토링, 모의 면접까지.
hanghae99.spartacodingclub.kr
'멋진 개발자 > Network' 카테고리의 다른 글
개발자 취준 기록 37 - HTTP 상태 코드 (0) | 2024.04.01 |
---|---|
개발자 취준 기록 32 - HTTP Method (0) | 2024.03.27 |
[항해 취업코스] 개발자 취준 기록 25 - HTTP & HTTPS (0) | 2024.03.20 |
[항해 취업코스] 개발자 취준 기록 24 - 쿠키와 세션 (0) | 2024.03.19 |
[항해 취업코스] 개발자 취준 기록 23 - TCP와 UDP (0) | 2024.03.18 |