[cs] Cors
목차

CORS & Proxy

CORS & Proxy 에 대해서

01. 먼저 알고 가자.. 출처(Origin) 가 뭘까

Origin 어떻게 확인하나 !

02. 같은 출처와 다른 출처의 구분

여기서 중요 포인트 !

03. CORS 정확히 알아야 하는 이유

04. CORS 동작 순서

우선 관련 헤더를 살펴보자

다음 그림으로 동작 순서를 살펴보면..

05. 그러면 도대체 CORS를 해결할 수 있는 방법은 무엇 ?!

06. Proxy 와의 관계를 설명해 보자

CORS & Proxy

2024년 1월 12일

CORS & Proxy 에 대해서

  • 다음 사진으로 CORS(Cross-Origin Resource Sharing : 교차 원본 리소스 공유) 에러를 한번에 설명할 수 있다.

=> 여기서 “교차 출처”라고 하는 것은 “다른 출처”를 의미하는 것 => 허용기준 이라고 할수 있겠다. 그래서 CORS 에러라고 뜨는거임

mdImag

  • 자산의 보안을 유지하기 위해 대부분의 서버는 다른 요청을 제한
  • 이 정책은 CSRF(교차 사이트 요청 위조) 공격 및 다른 웹 서버의 개인 정보 도용을 포함한 악의적인 활동에 대응하여 만들어졌다.

CSRF(교차 사이트 요청 위조) 공격 이 뭔ㄷㅔ..

  • CSRF 공격이 이뤄지려면 다음 조건이 만족되어야 한다.

    • 위조 요청을 전송하는 서비스(페이스북)에 희생자가 로그인 상태
    • 희생자가 해커가 만든 피싱 사이트에 접속

=> 페이스북, 네이버, 구글 등의 유명 사이트는 보통 PC에서 자동 로그인을 해놓은 경우가 많고 피싱 사이트는 피싱 메일, 음란 사이트(?) 등을 통해 접속될 수 있다.

=> 희생자가 해커가 만든 피싱 사이트를 하지 않더라도 해커가 XSS 공격을 성공한 정상 사이트를 통해 CSRF 공격이 수행될 수 도 있다.

mdImag

01. 먼저 알고 가자.. 출처(Origin) 가 뭘까

  • 서버의 위치를 의미하는 https://google.com 과 같은 URL들은 마치 하나의 문자열 같아 보여도, 사실은 여러 개의 구성 요소로 이루어져있다.

mdImag

  • 이때 출처는 Protocol(Scheme)Host, 그리고 위 그림에는 나와있지 않지만 :80, :443과 같은 포트 번호까지 모두 합친 것을 의미한다. => 만약 https://google.com:443 과 같이 출처에 포트 번호가 명시적으로 포함되어 있다면 이 포트 번호까지 모두 일치해야 같은 출처라고 인정된다.

Origin 어떻게 확인하나 !

  • 우리는 브라우저의 개발자 도구의 콘솔에서 Location 객체가 가지고 있는 origin 프로퍼티에 접근함으로써 손 쉽게 어플리케이션이 실행되고 있는 출처를 알아낼 수도 있다.
console.log(location.origin); // "https://evan-moon.github.io"

02. 같은 출처와 다른 출처의 구분

  • 사실 두 개의 출처가 서로 같다고 판단하는 로직 자체는 굉장히 간단한데, 두 URL의 구성 요소 중 Scheme, Host, Port, 이 3가지만 동일하면 된다.

mdImag

여기서 중요 포인트 !

  • 이렇게 출처를 비교하는 로직이 서버에 구현된 스펙이 아니라 브라우저에 구현되어 있는 스펙이라는 것 !

  • 그러므로 CORS 정책을 위반하는 리소스 요청 => 해당 서버가 같은 출처에서 보낸 요청만 받겠다는 로직을 가지고 있는 경우가 아니라면 서버는 정상적으로 응답 => 브라우저가 이 응답을 분석해서 CORS 정책 위반이라고 판단 => 그 응답을 사용하지 않고 그냥 버림

mdImag

  • 즉, CORS는 브라우저의 구현 스펙에 포함되는 정책이기 때문에, 브라우저를 통하지 않고 서버 간 통신을 할 때는 이 정책이 적용되지 않는다. !

03. CORS 정확히 알아야 하는 이유

  • CORS 정책을 위반하는 리소스 요청 때문에 에러가 발생했다고 해도 서버 쪽 로그에는 정상적으로 응답을 했다는 로그만 남기 때문에, CORS가 돌아가는 방식을 정확히 모르면 에러 트레이싱에 난항을 겪을 수도 있다.

04. CORS 동작 순서

우선 관련 헤더를 살펴보자

  • Access-Control-Allow-Origin : 서버가 리소스에 액세스할 수 있는 원본을 지정할 수 있다.
  • Access-Control-Allow-Methods : 서버가 리소스를 요청할 때 허용되는 HTTP 메서드를 지정할 수 있다.

다음 그림으로 동작 순서를 살펴보면..

mdImag

  1. 브라우저 => 요청 헤더에 Origin이라는 필드에 요청을 보내는 출처를 함께 담아 보냄

  2. 서버 => 이 요청에 대한 응답을 할 때 응답 헤더의 Access-Control-Allow-Origin 이라는 값에 “이 리소스를 접근하는 것이 허용된 출처” 를 내려보냄

  3. 브라우저 => 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후 이 응답이 유효한 응답인지 아닌지를 결정

  • 크게 세가지로 말할수 있는데 Preflight Request(브라우저가 본 요청을 보내기 전에 보내는 예비 요청을 Preflight라고 부르는 것, 거의 이 시나리오를 마주친다),Simple Request, Credentialed Request => 나머지는 직접.. 알아보세요..ㅎ

05. 그러면 도대체 CORS를 해결할 수 있는 방법은 무엇 ?!

  1. 서버에서 ) 말을 잘듣기 : Access-Control-Allow-Origin 세팅하기 => 정석대로 서버에서 Access-Control-Allow-Origin 헤더에 알맞은 값을 세팅(와일드 카드 * 쓰지마라.. 큰거(보안적으로 심각한 이슈)온다.) => 백엔드 프레임워크의 경우에는 모두 CORS 관련 설정을 위한 세팅이나 미들웨어 라이브러리를 제공하고 있으니 세팅 자체가 어렵지는 않을 거임

  2. 클라이언트에서 ) Webpack Dev Server 로 리버스 프록싱: 사실 CORS를 가장 많이 마주치는 환경은 바로 로컬에서 프론트엔드 어플리케이션을 개발하는 경우임...ㅅㅂ

  • 프론트엔드 개발자는 대부분 웹팩과 webpack-dev-server를 사용하여 자신의 머신에 개발 환경을 구축

  • 이럴경우 사용해라 무엇을 ? Webpack Dev Server로 리버스 프록싱을 !!

  • 이렇게 설정을 해놓으면 로컬 환경에서 /api로 시작하는 URL로 보내는 요청에 대해 브라우저는 localhost:8000/api 로 요청을 보낸 것으로 알고 있지만, 사실 뒤에서 웹팩이 https://api.evan.com 으로 요청을 프록싱해주기 때문에 마치 CORS 정책을 지킨 것처럼 브라우저에게 구라치기 가능 ~ 우리는 원하는 서버와 자유롭게 통신을 할 수 있다.

=> 즉, 프록싱을 통해 CORS 정책을 우회할 수 있는 것이다.

module.exports = { devServer: { proxy: { "/api": { target: "https://api.evan.com", changeOrigin: true, pathRewrite: { "^/api": "" }, }, }, }, };
  1. 클라이언트에서 ) http-proxy-middleware : 이 라이브러리를 사용하면 손쉽게 프록시 설정 삽가능..

=> 근데요 있잖아요..? 이 방법은 실제 프로덕션 환경에서도 클라이언트 어플리케이션의 소스를 서빙하는 출처와 API 서버의 출처가 같은 경우에 사용하는 것이 좋다. 어플리케이션을 빌드하고 서버에 올리고 나면 더 이상 webpack-dev-server가 구동하는 환경이 아니기 때문에 프록싱이고 나발이고 이상한 곳으로 API 요청을 보내기 때문 ㅎㅎ

=> 예를 들어 API 서버의 출처는 https://api.evan.com 이고 클라이언트 어플리케이션을 서빙하는 서버의 출처는 https://www.evan.com 이라면, 다음과 같은 상황이 발생한다는 것이다. => 헛발질 한다고 보면 됨 ㅎ

로컬환경에서는... GET https://api.evan.com/me 200 OK 실제 서버에는 프록싱 로직이 없음... GET https://www.evan.com/api/me 404 Not Found

=> 결론 2, 3번도 로컬에서 가능한 방법이기 때문에 CORS를 우회하려는 시도는 그냥 깔끔하게 포기하고 똑똑한 아저씨들이 시키는 대로 CORS 정책을 지키도록 하자.(서버단과 부디 원할한 소통 쿠다사이 ~)

06. Proxy 와의 관계를 설명해 보자

mdImag

  • Proxy 서버란 ? 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다.

  • 서버와 클라이언트 사이에 중계기로서 대리로 통신을 수행하는 것을 가리켜 '프록시', 그 중계 기능 => 중계사 라고 보면됨

mdImag

  • 꼭 CORS 뿐만 아니라 다양한 사용목적을 가지는 Proxy 서버 친구를 참고해두자..

mdImag