교차 출처 리소스 공유(CORS)

설정 구성 샘플

동일 출처 정책은 서로 다른 출처의 리소스 간 상호작용을 방지하기 위해 클라이언트 측 웹 애플리케이션(웹브라우저 등)에서 적용되는 보안 정책입니다. 이 보안 조치는 악의적인 행동을 방지하는 데는 유용하지만 알려진 출처 간의 적법한 상호작용도 방지합니다. 예를 들어 example.appspot.com에 있는 App Engine에서 호스팅되는 페이지의 스크립트가 example.storage.googleapis.com에 있는 Cloud Storage 버킷에 저장된 리소스를 사용해야 할 수도 있습니다. 하지만 브라우저 관점에서 이 둘은 출처가 서로 다르기 때문에 브라우저는 example.appspot.com의 스크립트가 example.storage.googleapis.com의 리소스를 가져오는 것을 허용하지 않습니다.

교차 출처 리소스 공유(CORS)는 이 제한을 해결하기 위해 W3C(World Wide Web Consortium)에서 개발한 사양입니다. Cloud Storage는 버킷이 CORS를 지원하도록 구성하는 것을 허용함으로써 이 사양을 지원합니다. 위 예시에 이어 브라우저에서 example.storage.googleapis.com 버킷의 리소스를 example.appspot.com의 스크립트와 공유할 수 있도록 버킷을 구성할 수 있습니다.

CORS 구성의 구성요소에 대한 자세한 내용은 버킷 CORS 설정을 참조하세요.

CORS 작동 원리

단순 요청과 실행 전 요청이라는 두 가지 유형의 CORS 요청이 있습니다. 단순 요청은 바로 시작할 수 있습니다. 실행 전 요청은 기본 요청을 진행하기 전에 예비 '실행 전' 요청을 서버에 보내 권한을 얻어야 합니다. 다음 상황 중 어느 하나라도 참인 경우 실행 전 요청입니다.

  • GET, HEAD, POST 외의 메서드를 사용합니다.
  • POST 메서드를 text/plain, application/x-www-form-urlencoded, multipart/form-data가 아닌 Content-Type과 함께 사용합니다.
  • 커스텀 헤더를 설정합니다. 예를 들면 X-PINGOTHER입니다.

브라우저가 Cloud Storage에 단순 요청을 보낼 때 다음과 같은 프로세스가 이루어집니다.

  1. 브라우저가 Origin 헤더를 요청에 추가합니다. Origin 헤더는 Origin:https://www.example.appspot.com과 같이 Cloud Storage 버킷의 리소스를 공유하기 위해 리소스 출처를 포함하고 있습니다.

  2. Cloud Storage가 요청의 HTTP 메서드와 Origin 헤더의 값을 대상 버킷의 CORS 구성에 있는 메서드출처 정보와 비교하여 일치하는 항목이 있는지 확인합니다. 일치하는 항목이 있으면 Cloud Storage가 Access-Control-Allow-Origin 헤더를 응답에 포함합니다. Access-Control-Allow-Origin 헤더는 초기 요청에 있는 Origin 헤더의 값을 포함합니다.

  3. 브라우저가 응답을 받고 Access-Control-Allow-Origin 값이 원래 요청에 지정된 도메인과 일치하는지를 확인합니다. 일치하면 요청이 성공합니다. 일치하지 않거나 응답에 Access-Control-Allow-Origin 헤더가 없는 경우에는 요청이 실패합니다.

실행 전 요청은 다음 단계를 먼저 수행합니다. 성공하면 단순 요청과 동일한 프로세스를 따릅니다.

  1. 브라우저가 기본 요청의 Requested MethodRequested Headers를 포함하는 OPTIONS 요청을 보냅니다.

  2. Cloud Storage가 응답하고 대상 리소스에서 허용하는 HTTP 메서드 및 헤더의 값을 반환합니다. 실행 전 요청에 있는 메서드 또는 헤더 값 중 하나라도 대상 리소스에서 허용하는 메서드 및 헤더 집합에 들어 있지 않으면 요청이 실패하고 기본 요청이 전송되지 않습니다.

위 프로세스는 CORS를 간단하게 설명한 것입니다. 자세한 설명은 가져오기 사양을 읽어보세요.

Cloud Storage CORS 지원

Cloud Storage를 사용하면 버킷 수준에서만 CORS 구성을 설정할 수 있습니다. 다양한 도구를 사용하여 버킷의 CORS 구성을 설정할 수 있습니다. 그러나 다양한 Cloud Storage 엔드포인트는 서로 다른 방식으로 CORS 요청을 처리합니다.

  • JSON API 엔드포인트는 CORS 요청을 항상 허용하고 버킷에 설정된 구성에 관계없이 CORS 응답 헤더의 기본값을 반환합니다.

  • XML API 엔드포인트는 버킷 구성에 따라서만 CORS 요청을 허용하고 해당 구성에 대한 응답의 특정 CORS 헤더 값을 반환합니다.

  • 인증된 브라우저 다운로드 엔드포인트 storage.cloud.google.com은 CORS 요청을 허용하지 않습니다. Google Cloud 콘솔은 각 객체의 공개 URL 링크에 이 엔드포인트를 제공합니다.

다음 XML API 요청 URL 중 하나를 사용하여 CORS 헤더를 포함하는 Cloud Storage에서 응답을 받을 수 있습니다.

storage.googleapis.com/BUCKET_NAME
BUCKET_NAME.storage.googleapis.com

XML API 요청 URL에 대한 자세한 내용은 요청 엔드포인트를 참조하세요.

CORS 구성의 구성요소

XML API를 사용할 때 버킷의 CORS 구성에 설정한 값에 따라 Cloud Storage가 HTTP 응답에서 반환하는 CORS 헤더가 결정됩니다. JSON API를 사용할 때 Cloud Storage는 버킷 구성을 평가하지 않고 대신 기본 헤더 값을 반환합니다.

다음 표에서는 CORS 구성의 필드와 XML 및 JSON API의 응답 동작에 대해 설명합니다. 이러한 필드의 사용 방법은 CORS 구성 예시를 참조하세요.

필드1 설명 XML API 응답 동작 JSON API 응답 동작
origin 이 Cloud Storage 버킷과의 교차 출처 리소스 공유를 허용하려는 출처를 지정합니다. 예를 들면 https://origin1.example.com입니다. 브라우저 요청의 출처가 CORS 구성의 출처와 일치하면 Cloud Storage가 브라우저에 Access-Control-Allow-Origin을 반환합니다. 일치하는 항목이 없으면 Cloud Storage가 응답에 Access-Control-Allow-Origin을 포함하지 않습니다. 모든 출처에 대한 액세스 권한을 부여하는 와일드 카드 값(<Origin>*</Origin>)을 제공할 수 있습니다. Cloud Storage는 요청의 출처로 설정된 Access-Control-Allow-Origin 헤더를 반환합니다.
method

이 Cloud Storage 버킷과의 교차 출처 리소스 공유를 허용하려는 HTTP 메서드를 지정합니다. 성공적인 실행 전 요청에 대한 응답으로 이 값이 Access-Control-Allow-Methods 헤더에 반환됩니다.

OPTIONS는 브라우저에서 실행 전 요청을 시작하는 데 사용하는 표준 메서드이므로 CORS 구성에서 OPTIONS를 지정해서는 안 됩니다.

Cloud Storage는 DELETE, GET, HEAD, POST, PUT 메서드를 지원합니다.

Cloud Storage는 Access-Control-Request-Methods 헤더의 브라우저에서 전송된 메서드를 버킷의 CORS 구성과 대조합니다. 일치하는 항목이 없으면 Cloud Storage는 CORS 응답 헤더가 없는 200 응답 코드를 반환합니다.

Cloud Storage는 DELETE, GET, HEAD, PATCH, POST, PUT 메서드로 설정된 Access-Control-Allow-Methods 헤더를 반환합니다.
responseHeader 이 Cloud Storage 버킷과의 교차 출처 리소스 공유를 허용하려는 헤더를 지정합니다. 성공적인 실행 전 요청에 대한 응답으로 이 값이 Access-Control-Allow-Headers 헤더에 반환됩니다. 실행 전 요청의 경우 Cloud Storage는 Access-Control-Request-Headers 헤더의 브라우저에서 전송된 헤더를 버킷의 CORS 구성과 대조합니다. 일치하는 항목이 없으면 Cloud Storage는 CORS 응답 헤더를 반환하지 않습니다. Cloud Storage는 Access-Control-Request-Headers 헤더에 지정된 값과 동일한 Access-Control-Allow-Headers 헤더를 반환합니다.
maxAgeSeconds(선택사항) 프리플라이트 요청을 반복하기 전에 브라우저가 요청할 수 있는 시간(초)을 지정합니다. 이를 캐시 만료 시간이라고도 합니다. 실행 전 요청에 대한 응답으로 이 값이 Access-Control-Max-Age 헤더에 반환됩니다. 예를 들어 3600은 캐시 만료 시간을 1시간으로 설정합니다. Cloud Storage는 지정된 캐시 만료 시간이 있는 Access-Control-Max-Age 헤더를 반환합니다. 이 필드를 생략하면 Cloud Storage가 기본값 3600을 반환합니다. Cloud Storage는 기본값이 3600Access-Control-Max-Age 헤더를 반환합니다.

1 필드 열에 문서화된 이름은 JSON API와 관련됩니다. XML API를 사용하여 CORS 구성을 설정할 때는 XML 관련 형식을 사용하세요.

추가 고려 사항

다음 표에서는 사용자 인증 정보 또는 액세스 제어 헤더를 사용하여 요청할 때의 고려 사항에 대해 설명합니다.

속성 또는 헤더 설명 XML API 응답 동작 JSON API 응답 동작
사용자 인증 정보 쿠키, 승인 헤더, TLS 클라이언트 인증서 Cloud Storage는 Access-Control-Allow-Credentials 헤더를 반환하지 않습니다. CORS 사용자 인증 정보는 XML API에서 지원되지 않습니다.

단순 요청의 경우 CORS 요청이 승인되었으면 Access-Control-Allow-Credentials 헤더가 true로 설정됩니다.

실행 전 요청의 경우 Access-Control-Request-Method가 비어 있으면 Cloud Storage는 Access-Control-Allow-Credentials를 true로 설정하고 404 - Not Found로 요청을 거부합니다.

노출된 헤더 실행 전 요청의 경우 Access-Control-Request-Headers 요청 헤더는 이후 CORS 요청에 포함될 수 있는 헤더를 나타냅니다. Access-Control-Expose-Headers 응답 헤더는 서버 응답에 포함되며 클라이언트에 노출될 수 있는 헤더를 나타냅니다. 단순 요청의 경우 Access-Control-Expose-Headers는 CORS 구성에 응답 헤더 값을 나열합니다. 단순 요청의 경우 Access-Control-Expose-Headers는 공통 HTTP 헤더 목록에 포함된 경우 Access-Control-Request-Headers에 지정된 값을 반환합니다.

버킷의 외부 리소스 액세스 허용

일부 경우에는 Cloud Storage에 호스팅된 스크립트가 Cloud Storage 외부 웹사이트에 호스팅된 정적 리소스에 액세스하도록 허용해야 할 수 있습니다. 이러한 시나리오에서 해당 웹사이트는 storage.googleapis.com의 콘텐츠에 액세스를 허용할 수 있도록 CORS 헤더를 사용합니다.

이 데이터 액세스를 위해 특정 버킷을 전용으로 지정하는 것이 좋습니다. 이 방식은 사이트에 있는 정적 리소스가 실수로 모든 storage.googleapis.com에 과도하게 노출되는 것을 방지합니다. 예를 들어 mybucket이라는 버킷을 데이터 액세스 전용으로 사용하려면 웹사이트에서 CORS 헤더에 Access-Control-Allow-Origin: https://storage.googleapis.com 대신 Access-Control-Allow-Origin: https://mybucket.storage.googleapis.com를 사용해야 합니다.

클라이언트 측 CORS 지원

대부분의 브라우저는 XMLHttpRequest 객체를 사용하여 교차 도메인 요청을 설정합니다. XMLHttpRequest는 올바른 헤더를 삽입하고 서버와의 CORS 상호작용을 처리하기 위한 모든 작업을 다룹니다. Cloud Storage 버킷에서 CORS 지원을 활용하기 위해 새로운 코드를 추가할 필요가 없습니다.

다음 단계