본문 바로가기
개발일지/WIL

[WIL] 항해99 (9기) - 5주차 회고

by 깸뽀 2022. 10. 24.
728x90

CORS란?

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행합니다. - mdn 설명 -

 

출처(Origin)란 ?

출처 ) https://evan-moon.github.io/2020/05/21/about-cors/

서버의 위치를 의미하는 https://google.com 과 같은 URL들은 마치 하나의 문자열 같아 보여도, 사실은 여러 개의 구성 요소로 이루어져있다. 이때 출처는 Protocol과 Host, 그리고 위 그림에는 나와있지 않지만 :80, :443과 같은 포트 번호까지 모두 합친 것을 의미한다. 즉, 서버의 위치를 찾아가기 위해 필요한 가장 기본적인 것들을 합쳐놓은 것이다.

또한 출처 내의 포트 번호는 생략이 가능한데, 이는 각 웹에서 사용하는 HTTP, HTTPS 프로토콜의 기본 포트 번호가 정해져있기 때문이다. HTTP가 정의된 RFC 2616 문서를 보면 다음과 같이 기본 포트 번호가 함께 정의되어있는 것을 볼 수 있다. 그러나 만약 https://google.com:443과 같이 출처에 포트 번호가 명시적으로 포함되어 있다면 이 포트 번호까지 모두 일치해야 같은 출처라고 인정된다. 하지만 이 케이스에 대한 명확한 정의가 표준으로 정해진 것은 아니기 때문에, 더 정확히 이야기하자면 어떤 경우에는 같은 출처, 또 어떤 경우에는 다른 출처로 판단될 수도 있다. 

우리는 브라우저의 개발자 도구의 콘솔에서 Location 객체가 가지고 있는 origin 프로퍼티에 접근함으로써 손 쉽게 어플리케이션이 실행되고 있는 출처를 알아낼 수도 있다.

 

 

CORS가 필요한 이유

출처가 다른 두 개의 어플리케이션이 마음대로 소통하는 환경은 위험한 환경이다. 웹에서 돌아가는 클라이언트 애플리케이션은 사용자 공격에 매우 취약하다. 개발자 도구만 열더라도 DOM, JavaScript코드 등 각종 통신 정보를 쉽게 열람할 수 있다. 이를 통해서 사용자가 악의를 가지고 다른 사이트로 본 사이트를 모방할 수 잇다. 이렇게 다른 출처의 어플리케이션이 통신하는 것에 제약이 없다면, 기족 사이트와 동일하게 동작하여 사용자의 정보가 탈취되기 쉬워진다.

 

Same Origin Policy(동일 출처 정책)

동일 출처 정책은 웹 브라우저에서 보안을 강화하기 위하여 동일한 출처에서만 리소스를 주고 받도록 하는 정책이다.

동일한 출처는 URL 중에서도 프로토콜, 도메인 주소, 포트 번호가 같은 것을 의미한다.

 

http://github.com:80를 예시로 들자면 http : 프로토콜, github.com : 호스트, 80 : 포트

그럼 SOP는 동일한 프로토콜, 호스트, 포트의 리소스만 허용한다는 것인데 가상의 시나리오를 들어보겠다.

 

1. 클라이언트가 페이스북에 로그인(토큰 발급)을 한다.
2. 해커가 클라이언트에게 `http://hacker.ck`라는 URL을 보냄.
3. 클라이언트가 해커가 보낸 링크가 흥미로워서 클릭함.
4. 해커가 보낸 페이지에는 클라이언트의 토큰을 이용하여 개인정보를 탈취하는 스크립트가 포함되어 있음.

페이스북 서버가 토큰만으로 사용자를 판단한다면.. 클라이언트와 해커의 요청을 구분하기 힘들 것이다.

반면에 요청 URL을 확인한다면 클라이언트의 출처는 http://www.facebook.com/~이고 해커의 출처는 http://hacker.hc일테니 서로 다른 출처라는 것을 확인하여 악의적인 요청을 방지할 수 있다.

위와 같은 상황, 요청의 출처가 다르다면 Cross Origin SOP에 위반이라고 한다.
하지만 외부 라이브러리도 사용해야 하는데 요청과 리소스를 매번 동일한 출처로만 받을 수는 없다.

이 때 필요한 것이 CORS이다.

 

CORS (Cross Origin Resource Sharing)

CORS는 다른 출처의 자원을 공유하는 것이다.
MOZILLA에서는 CORS를 아래와 같이 설명하고 있다.

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

CORS 접근제어에 사용되는 3가지의 시나리오가 있다.

  • 단순 요청 (Simple Request)
  • 사전 요청 (Preflight Request)
  • 인증 요청 (Credentialed Request)

단순 요청 (Simple Request)

Preflight 요청 없이 바로 요청을 보낸다.
Simple Request는 아래와 같은 조건을 만족해야한다.

  • 메서드 : GET, POST, HEAD
  • Content-Type은 아래 셋 중 하나여야 한다.
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 헤더 : Accept, Accept-Language, Content-Language, Content-Type 만 허용 한다.

사전 요청 (Preflight Request)

사전 요청은 OPTIONS 메서드를 통해 다른 도메인 리소스에 요청이 가능한지 확인하는 작업이다.
요청이 가능한 것을 확인하면 실제 요청을 보낸다.

Preflight Request

  • Origin : 요청 출처
  • Access-Control-Request-Method : 실제 요청의 메서드
  • Access-Control-Request-Headers : 실제 요청의 추가 헤더

Preflight Response

  • Access-Control-Allow-Origin : 허가 출처
  • Access-Control-Allow-Methods : 허가 메서드
  • Access-Control-Allow-Headers : 허가 헤더
  • Access-Control-Max-Age : Preflight 응답 캐시 시간

여기서 Preflight Response의 응답 코드는 200대여야하고 Body는 비어있는 것이 좋다.

인증 요청 (Credentialed Request)

인증 관련 헤더를 포함할 때 사용하는 요청이다.

클라이언트

쿠키 또는 JWT 토큰을 담아 보낼 경우 credentials : include 를 포함하여 보낸다.

서버

Access-Control-Allow-Credentials : true 해야 클라이언트의 인증 포함 요청에 허용이 가능하다.

CORS

CORS 해결 방법에는 세 가지가 있다.

  • 프론트 프록시 서버 설정
    • 프론트 서버에서 백엔드 서버로 요청을 보낼 때, 대상의 URL을 변경한다.
  • 직접 헤더 설정
    • 직접 헤더에 설정을 추가한다.
  • 스프링부트 설정
    • 설정 클래스를 만들고 WebMvcConfigurer을 구현하면 addCorsMappings란 메서드를 사용하여 CORS의 출처 및 설정 관리를 할 수 있다.

 

< 참 고 >

 

 

728x90

댓글