CORS 란 무엇일까?


:raising_hand: 프론트엔드 개발관련 공부내용을 기록하는 포스트 입니다.


image

1. 개요


시스템을 운영하면서 아래와 같은 오류를 다들 한번쯤은 보았을 것이다.

Access to fetch at ‘https://api.lubycon.com/me’ from
origin ‘http://localhost:3000’ has been blocked by CORS policy:
No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
If an opaque response serves your needs,
set the request’s mode to ‘no-cors’ to fetch the resource
with CORS disabled.

웹 개발을 하다보면 CORS 정책 위반으로 인해 에러가 발생하는 경우가 종종 있었다.

단순한 API 통신을 통한 데이터 요청/응답 을 했는데도 불구하고 크롬 개발자도구에는 당황스런 오류가 발생하는 것이다.

이번 포스팅에서는 구글링 중 CORS에 대해 공부하다 정말 좋은 블로그를 발견하여 해당 블로그를 참고하여 나만의 개념을 확립하고자 작성한다.

2. CORS 란 무엇일까?


브라우저엣서는 보안적인 이유로 cross-origin HTTP 요청들을 제안한다.

따라서, cross-origin 요청에 대한 서버의 동의, 브라우저의 동의 등 여러가지 해당 리소스에 대한 출처의 확인이 필요하다.

이렇게 브라우저에서 특정 리소스를 요청할 경우 허락 및 거절하는 메커니즘을 HTTP-header를 통해서 가능한데 이를 Cross-Origin Resource Sharing(CORS) 라고 부른다.

즉, 결과적으로 브라우저에서 cross-origin 요청을 안전하게 할 수 있도록 하는 메커니즘 이다.

우리가 사용하는 웹 생태계 에서CORS관련 이슈가 발생하는 이유는 CORS정책을 위반해서 발생한다.

개발자의 입장에서 여러 신경써야 하는 부분이 늘어나지만, CORS라는 방어막이 존재하기에 우리는 이곳 저곳에서 가져오는 리소스가 안전하다는 최소한의 보장을 받을 수 있는 것이다.

2-1. Origin(출처) 의 역할

우리가 브라우저에서 특정 사이트를 들어가는데 볼 수 있는 URL의 구성요소에 대해서 알아보자.

image

여기서 출처(Origin)은 ProtocolHost 그리고 Port 까지를 의미한다. 즉, 서버의 위치를 찾아가기 위해 필요한 가장 기본적인 것들을 합쳐놓은 것이다.

Port의 경우에는 생략이 가능하다.

HTTP, HTTPS 프로토콜의 기본 포트 번호가 명시되지 않을 경우 80으로 정의되기 때문이다.

하지만, https://XXX.com:443 과 같이 포트 번호가 명시적으로 포함 되어 있으면 포트번호까지 일치해야 같이 출처(Origin)이라 인정한다.

브라우저의 개발자도구에서 location 객체가 가지고 있는 origin 프로퍼티에서 해당 사이트의 출처를 알아낼 수 있다.

image

3. SOP(Same-Origin Policy)


웹 생태계에는 다른 출처(Origin)로의 Resource 요청을 제한하는 것과 관련된 두가지 정책이 존재한다.

하나는 현재 다루고 있는 CORS이며 다른 하나는 SOP(Same-Origin Policy) 이다.

SOP는 2011년, RFC 6454에 처음 등장한 보안 정책이다.

이는 “같은 출처에서만 리소스를 공유할 수 있다” 라는 규칙을 갖는다.

하지만, 다른 출처에 있는 리소스에 대한 접근을 모두 막을 수 없기에 몇 가지의 예외 조항을 두고 예외를 두었다.

그 중 하나가 CORS정책을 지킨 리소스 요청일 경우이다.

Access to network resources varies depending on whether
the resources are in the same origin as the content attempting
to access them.

Generally, reading information from another origin is forbidden.
However, an origin is permitted to use some kinds of resources retrieved from other origins.
For example, an origin is permitted to execute script, render images, and apply style sheets from any origin.

 Likewise, an origin can display content from another origin, such as an HTML document in an HTML frame.

 Network resources can also opt into letting other origins read their information, for example, using Cross-Origin Resource Sharing.

이처럼 특정 도메인에서 다른 출처의 리소스를 가져다 사용하기 위해서는 SOP정책을 지켜야 하며, 최소한 CORS 정책은 지켜야 한다는 의미 이다.

그러면 왜 이런 규약과 제한을 두는 것일까?

4. SOP , CORS 와 같은 규약이 생겨난 이유


이렇게 힘들게 규약을 만들고 제한하는 이유는 웹 생태계에 존재하는 수만은 공격들로 인한 피해를 방지하기 위해서 이다.

우리는 여러 어플리케이션을 사용하면서 우리의 개인정보를 포함한 다양한 정보를 아무런 의심없이 네트워크상으로 전달하게 된다.

하지만 우리가 사용하는 이 브라우저는 마음만 먹으면 굉장히 많은 정보를 볼 수 있고, 이로인해 너무나도 많은 공격에 취약한 환경이다.

개발자도구를 통해 DOM 의 정보, Network를 통해 어떻게 서버와 통신하는지, 응답받은 데이터의 출처는 어디인지 등 다양한 정보들을 누구나 확인할 수 있다.

흔한 예로 들면, 현재 회사앱에서 예전에 XSS 보안 정책에 걸린적이 있다고 한다.(본인이 입사하기 전)

XSS(Cross-site Scripting) 이란 웹 사이트 관리자가 아닌 이가 웹 페이지에 악성 스크립트를 삽입하여 공격하는 방법이다.

최근에는 Webpack과 같은 모듈 번들러를 통하여 난독화를 하기 때문에 이러한 공격이 어느정도는 방어가 되지만 난독화가 되지 않은 사이트의 경우 굉장히 위험한 공격일 수 있다.

5. 경우에 따른 Origin(출처)의 구분


위에서 우리가 말했던 Origin(출처)가 같은가 다른가에 대해서 판단은 두개의 URL 구성 중 Scheme, Host, Port 이 3가지가 동일한지에 따라 결정된다.

예를들어, https://jjou33.github.io:80의 출처가 https://, jjou33.github.io 호스트를 가지며 :80 포트를 사용하고 있으면, 그 외 어떤 경우에도 이는 같은 출처로 인정된다.

  URL 동일 출처 판단 이유
1 https://jjou33.github.io/vuedev/slot/ O Scheme, host, port 모두 동일
2 https://XXX@jjou33.github.io O Scheme, host, port 모두 동일
3 http://jjou33.github.io/vuedev/slot/ X Scheme(http !== https)이 다름
4 https://google.com X host가 다름
5 https://jjou33.github.io:8000 X Port 가 다름

위에서 설명했듯이 우리가 port를 직접 명시하지 않으면 기본적으로 80번 포트로 들어가게 된다.

5-1. 출처 비교 주체

위에서 설명했던 Origin(출처)의 비교를 하는 주체는 브라우저 로직이다.

추후 다음 포스팅에서 실제 CORS의 동작에서 포스팅 하겠지만, 실제로 응답을 비교하는 과정은 아래와 같다.

  1. browserGET 메서드를 통해 특정 서버에 리소스를 요청한다.
  2. 만약 서버에 같은 출처에서만 받는다는 로직 혹은 설정이 되어 있지 않다면 서버는 정상적으로 리소스를 응답한다.
  3. 브라우저는 해당 응답을 확인하고 CORS정책에 위반 되었다고 판단되면 해당 응답을 사용하지 않고 버린다.

위와 같은 과정으로 인해 서버간 통신에서는 CORS 정책이 적용되지 않고, 실제로 서버는 정상적인 응답을 하였기에 에러 로그가 남지 않고 정상 응답 로그만 남게 될 것이다.

다음 포스팅


이제 위 내용을 통해 CORS는 무엇일까? 라는 의문에 대한 답과 전체적인 그림이 머릿속에 그려지는 것 같다.

이제 다음 포스팅에서는 실제로 CORS가 어떻게 동작하는지에 대해 포스팅을 진행해보도록 한다.

참조 사이트