[Computer Science] CORS란?

HyungJin Han·2023년 2월 17일
0

Computer Science

목록 보기
6/10
post-thumbnail

1. CORS의 정의

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 브라우저가 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.

쉽게 정리하자면, 사용자가 지금 접속한 사이트와 다른 출처의 릴소스를 사용하려 할 때, 브라우저가 참고하는 화이트 리스트라고 할 수 있다.

만약, 이 리스트에 없다면 콘솔 창에 빨갛게 CORS 에러를 마주하게 된다.


2. SOP란?

동일 출처 정책(Same-Origin Policy)은 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식으로, 동일 출처 정책은 잠재적으로 해로울 수 있는 문서를 분리함으로써 공격받을 수 있는 경로를 줄여준다.

2-1. 동일 출처란?

프로토콜 / 호스트 / 포트 3가지가 모두 동일하면 동일 출처라고 할 수 있다.

URL동일 출처 여부
http://hhj.blog.com/dir/other기본 URL
http://hhj.blog.com/dir3/other1동일 출처 ⭕ - 경로만 다름
https://hhj.blog.com/dir/other동일 출처 ❌ - 프로토콜(https)이 다름
http://hhj.blog.com:81/dir/other동일 출처 ❌ - 포트가 다름 (기본 http:// 는 80, https:// 는 443)
http://jhh.blog.com/dir/other동일 출처 ❌ - 호스트(jhh)가 다름

동일 출처가 아닌데 ajax 요청을 보내면 CORS error를 만나게 되며, 즉, 동일 출처가 아닐 때 요청을 막는 것은 SOP이고, 요청이 가능하도록 하는 것이 CORS이다.

2-2. 왜 동일 출처 정책이 필요한가?

위의 그림을 통해 예시를 들자면,

  1. 유저가 어떤사이트에 접속하고 로그인을 하면, 브라우저의 토큰 등의 로그인 정보가 쿠키에 저장된다.

  2. 이때 로그인 했던 사이트에 접속할때 쿠키를 요청에 같에 보내어 로그인되었다고 판단한다.

  3. 즉, 인증 정보가 브라우저의 쿠키, 세션등의 스토리지에 저장되어 있고 이를 특정 요청에 같이 실어 보내어 인증을 진행하는 것이다.

  4. 만일 악의적인 사이트가 있다면 해당 사이트 접속시 JavaScript 코드가 유저의 브라우저에 다운로드되게 된다.

  5. 악의적인 사이트의 JavaScript 코드가 유저의 브라우저에 저장된 쿠키나 세션등에 접근할 수 있다.

  6. 이를 이용해 유저의 인증정보를 이용해 정보를 탈취할 수 있게된다.

원래 보안을 위해 다른 출처의 리소스를 접근하는 것이 불가능했지만, 웹 생태계가 다양해지면서 여러 서비스들끼리 자유롭게 데이터가 주고 받아질 필요가 생겼다.

그런데, 다른 사이트 간의 요청들을 브라우저가 막고 있기 때문에 이를 허용해주기 위해 어떠한 기준을 충족시키면 리소스를 공유할 수 있도록 만들어진 체제가 바로 CORS다.


3. CORS의 동작원리

CORS 동작의 시나리오는 다음 2가지로 나뉜다.

3-1. Simple Request

예비 요청을 보내지 않고, 서버에게 바로 본 요청을 전송한다.

이 후 서버가 응답 헤더에 Access-Control-Allow-Origin과 같은 값을 보내주면 그때 브라우저가 CORS 정책 위반 여부를 검사하는 방식이다.

GET이나 POST 등 일정 조건에 요청들에 대해 사용된다.

  1. 기본적으로 웹은 다른 출처의 리소스를 요청할 때는 HTTP 프로토콜을 사용하여 요청을 하는데, 이때 브라우저는 요청 헤더에 Origin 필드에 요청을 보내는 출처를 담아 전송한다.

  2. 서버는 요청에 대한 응답을 하는데, 응답 헤더에 Access-Control-Allow-Origin이라는 항목에 이 리소스를 접근하는 것이 허용된 출처를 명시해준다.

    Access-Control-Allow-Origin: * 처럼 와일드카드(*)를 사용하면 모든 origin 요청을 허용하는게 된다.

  3. 이후, 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교한 후 이 응답 가능 여부를 결정한다.

요청 시 headerorigin 항목에 URL(프로토콜/호스트/포트) 정보가 담겨있고, 응답 header에 Access-Control-Allow-Origin 항목에 요청시 origin 항목의 URL 정보가 있다면 브라우저는 응답을 받아오게 되고 없다면, 거부하게되며 CORS error가 나타나게 된다.

이러한 에러를 해결할 수 있도록, Spring이나 Django, Express 등의 문서에 CORS 옵션 설정하는 방법이 잘 나와있다.

3-2. Preflight Request

요청을 한번에 보내는 것이 아닌 예비 요청과 본 요청으로 나누어서 서버로 전송한다.

본 요청을 보내기 전 미리 예비로 보내는 요청을 Preflight라고 하며, HTTP 메서드 중 OPTIONS 메서드를 사용한다.

서버는 예비 요청에 대한 응답으로, 어떤 요청을 허용하고 또 금지하는지에 대한 정보를 응답 헤더에 담아 보낸다.

예비 요청으로 본 요청이 안전한지 확인한 다음에야 본격적으로 요청을 보낼 수 있다.

PUT이나 DELETE 등 서버 데이터에 영향을 줄 수 있는 요청들이기 때문에 먼저 요청의 허용 여부를 검증하는 것이다.

만약, 토큰 등 사용자 식별 정보가 담긴 요청에 대해서는 보다 엄격하다.

요청 옵션에 crendentials 항목을 true로 세팅해야 하고, 서버에서도 모든 출처를 허용하는 와일드카드 (*)가 아닌 요청 웹페이지의 주소를 정확히 명시한 다음 Access-Control-Allow-Credentials 항목을 true로 설정해주어야 한다.


참고 사이트

gwanuuoo.log - CORS란 무엇인가?
hinyc.log - CORS ? 쉽게 알아보자

profile
토끼보다는 거북이처럼 꾸준하게

0개의 댓글