[Network] CORS란?

GonnabeAlright·2021년 11월 22일
0
post-thumbnail

CORS(Cross Origin Resource Sharing)란

  • 웹 서버에게 보안 cross-domain 데이터 전송을 활성화하는 cross-domain 접근 제어권을 부여합니다.

배경

  • 처음 전송되는 리소스의 도메인과 다른 도메인으로부터 리소스가 요청될 경우 해당 리소스는 cross-origin HTTP 요청에 의해 요청된다.
  • 보안 상의 이유로, 브라우저들은 스크립트 내에서 초기화되는 cross-origin HTTP 요청을 제한한다.
    • 예를 들면, XMLHttpRequest는 same-origin 정책을 따르기에 XMLHttpRequest을 사용하는 웹 어플리케이션은 자신과 동일한 도메인으로 HTTP 요청을 보내는 것만 가능했다.
    • 웹 애플리케이션을 개선시키기 위해, 개발자들은 브라우저 벤더사들에게 XMLHttpRequest가 cross-domain 요청을 할 수 있도록 요청했고 이에 따라 CORS가 생겼다.

과정

  • CORS 요청시에는 미리 OPTIONS 주소로 서버가 cors를 허용하는지 물어본다.
  • 이때 Access-Control-Request-Method로 실제로 보내고자 하는 메서드를 알리고,
  • Access-Control-Request-Headers로 실제로 보내고자 하는 헤더들을 알린다.
  • Allow 항목들은 Request에 대응되는 것으로, 서버가 허용하는 메서드와 헤더를 응답하는데 사용된다.
  • Request랑 Allow가 일치하면 CORS 요청이 이루어진다.

CORS의 종류

  • Simple Request
  • Preflight Request
  • Credential Request
  • Non-Credential Request

Simple Request (다음 3가지를 만족할 경우)

  1. GET, HEAD, POST 중 한 가지 방식을 사용
  2. POST일 경우 Content-type이 아래 셋 중 하나를 만족
  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain
  1. 커스텀 헤더를 전송하지 않아야 함.

파란 블록의 HTTP Request는 foo.example로부터 온 요청
노란 블록의 HTTP Response는 bar.other로부터 온 응답
Access-Control-Allow-Origin: * 는 bar.other이 cross-site 방식 내 모든 도메인으로부터 접근이 가능하다는 뜻이다.
만약 요청한 페이지인 foo.example만을 포함했다면 Access-Control-Allow-Origin: foo.example로 표기

Preflight Request

Preflight(예비) 요청을 먼저 보내고 서버가 이에 응답이 가능한 지 확인합니다. 예비 요청은 OPTION 메소드로 HTTP 요청을 전송합니다. 이후 실제 Actual(본) 요청을 보냅니다. 그리고 서버가 이에 응답하며 통신하는 형태. Prelight Request는 위의 Simple Request에 해당하는 조건에 만족하면 안됩니다. 그렇기에 GET, HEAD, POST 이외 메소드를 사용하는 경우에만 사용 가능한 요청입니다. 만약 POST 요청을 사용할 경우에는 Content Type이 위의 3가지 경우가 아니거나 또는 커스텀 헤더를 사용할 수 있다는 점을 기억해야 합니다. 예비 요청과 예비 응답, 본 요청과 본 응답 총 4번의 형태로 구성되어 있습니다.

먼저 예비 요청 및 응답에 대해서 보자면 위에 말한 것처럼 OPTION 메소드를 이용하여 예비 요청을 보냈습니다. Access-Control-Request-Method: POST는 이후 본 요청에서 POST 메소드가 전달될 것을 미리 알려주는 역할을 합니다. Access-Control-Request-Headers: X-PINGOTHER는 본 요청에서 전달될 헤더 정보를 포함하고 있는데요. X-PINGOTHE이라는 커스텀 헤더가 전송될 예정입니다. 이후 이 예비 요청에 대한 응답이 위의 노란 블록처럼 전해집니다.

자세히 살펴봐야 할 것은 아래의 3줄입니다.

  • Access-Control-Allow-Origin: http://foo.example
  • Access-Control-Allow-Methods: POST, GET, OPTIONS
  • Access-Control-Allow-Headers: X-PINGOTHER
    셋 모두 Access-Control-Allow-* 이렇게 시작합니다. 당연히 허가된 정보를 뜻하는 것이지요. 이후에는 위의 Simple Request와 같이 본 요청과 응답이 수행됩니다.

Credential

세 번째는 HTTP Cookie와 HTTP Authentication 정보를 인식할 수 있게 해주는 요청입니다. 요청 시 xhr.withCredentials = true를 지정하는 것이 가장 큰 특징입니다.

크게 다른 점은 없습니다. 중요하게 살펴볼 곳은 한군데입니다.
Access-Control-Allow-Credentials: true
만약 위의 설정이 false라면 ? 브라우저는 이 요청을 거부할 것입니다.
거부할 때는 거부되었다는 어떠한 메시지도 전달하지 않아요. Response가 없습니다.

Non-Credential

마지막 요청은 Non-Credential 요청입니다. 사실 withCredentials 플래그는 디폴트 값이 false입니다. 그러니 위의 Credential 요청에서와 같이 처리해주지 않는다면 모든 요청이 바로 Non-Credential에 해당된다고 볼 수 있습니다.

0개의 댓글