크로스 오리진 리소스 공유란 무엇인가요?
크로스 오리진 리소스 공유(CORS)는 애플리케이션을 통합하기 위한 메커니즘입니다. CORS는 한 도메인에서 로드되어 다른 도메인에 있는 리소스와 상호 작용하는 클라이언트 웹 애플리케이션에 대한 방법을 정의합니다. CORS는 복잡한 애플리케이션의 경우 클라이언트 측 코드에서 서드 파티 API 및 리소스를 참조하는 경우가 많기 때문에 유용합니다. 예를 들어 브라우저를 사용하여 동영상 플랫폼 API에서 동영상을 가져오거나, 공용 글꼴 라이브러리의 글꼴을 사용하거나, 국가 날씨 데이터베이스의 날씨 데이터를 표시하는 애플리케이션이 여기에 포함됩니다. CORS를 사용하면 클라이언트 브라우저에서 데이터를 전송하기 전에 서드 파티 서버를 확인하여 요청 승인 여부를 확인할 수 있습니다.
크로스 오리진 리소스 공유가 중요한 이유는 무엇인가요?
인터넷 기술이 여전히 생소했던 과거에는 크로스 사이트 요청 위조(CSRF) 문제가 발생했습니다. 이 문제는 피해자의 브라우저에서 다른 애플리케이션으로 가짜 클라이언트 요청을 전송했습니다.
예를 들어 피해자가 은행 애플리케이션에 로그인하면 피해자를 속여 새 브라우저 탭에서 외부 웹 사이트를 로드합니다. 이 외부 웹 사이트는 피해자의 쿠키 보안 인증 정보를 사용하고 데이터를 릴레이하여 피해자인 것처럼 가장하면서 은행 애플리케이션에 데이터를 전달합니다. 그러면 권한이 없는 사용자에게 은행 애플리케이션에 대한 액세스 권한이 의도치 않게 부여됩니다.
이 CSRF 문제를 방지하기 위해 이제 모든 브라우저에서 동일 오리진 정책을 구현합니다.
동일 오리진 정책
오늘날의 브라우저에서는 클라이언트가 클라이언트의 URL과 동일한 오리진의 리소스로만 요청을 보낼 수 있습니다. 클라이언트 URL의 프로토콜, 포트 및 호스트 이름은 모두 클라이언트에서 요청하는 서버와 일치해야 합니다.
예를 들어 아래 URL의 오리진과 클라이언트 URL http://store.aws.com/dir/page.html의 오리진을 비교해 보세요.
URL |
성과 |
이유 |
http://store.aws.com/dir2/new.html |
동일한 오리진 |
경로만 다름 |
http://store.aws.com/dir/inner/other.html |
동일한 오리진 |
경로만 다름 |
https://store.aws.com/page.html |
다른 오리진 |
다른 프로토콜 |
http://store.aws.com:81/dir/page.html |
다른 오리진 |
다른 포트(http://는 기본적으로 포트 80임) |
http://news.aws.com/dir/page.html |
다른 오리진 |
다른 호스트 |
동일 오리진 정책은 매우 안전하지만 실제 사용 사례에는 유연하지 않습니다.
크로스 오리진 리소스 공유(CORS)는 동일 오리진 정책을 확장한 것입니다. 외부의 서드 파티와 승인 하에 리소스를 공유하려면 CORS가 필요합니다. 예를 들어 공개되거나 승인된 외부 API에서 데이터를 가져오려는 경우 CORS가 필요합니다. 또한 권한이 있는 서드 파티가 서버 리소스에 액세스하는 것을 허용하려는 경우에도 CORS가 필요합니다.
크로스 오리진 리소스 공유는 어떻게 작동하나요?
표준 인터넷 통신에서 브라우저는 애플리케이션 서버에 HTTP 요청을 보내고 HTTP 응답으로 데이터를 수신하여 표시합니다. 브라우저 용어에서는 현재 브라우저 URL을 현재 오리진이라고 하고 서드 파티 URL을 크로스 오리진이라고 합니다.
크로스 오리진 요청을 할 때 요청-응답 프로세스는 다음과 같습니다.
- 브라우저는 현재 오리진의 프로토콜, 호스트 및 포트에 대한 정보가 포함된 오리진 헤더를 요청에 추가합니다.
- 서버는 현재 오리진 헤더를 확인하고 요청된 데이터와 Access-Control-Allow-Origin 헤더로 응답합니다.
- 브라우저는 액세스 제어 요청 헤더를 확인한 후 반환된 데이터를 클라이언트 애플리케이션과 공유합니다.
서버에서 크로스 오리진 액세스를 허용하지 않는 경우에는 오류 메시지로 응답합니다.
크로스 오리진 리소스 공유 예제
예를 들어 https://news.example.com이라는 사이트가 있다고 합시다. 이 사이트는 partner-api.com에서 API 리소스에 액세스하려고 합니다.
https://partner-api.com의 개발자는 먼저 new.example.com을 허용된 오리진 목록에 추가하여 크로스 오리진 리소스 공유(CORS) 헤더를 구성합니다. 이를 위해 서버 구성 파일에 아래 줄을 추가합니다.
Access-Control-Allow-Origin: https://news.example.com
CORS 액세스가 구성되면 news.example.com에서 partner-api.com의 리소스를 요청할 수 있습니다. 모든 요청에서 partner-api.com은 Access-Control-Allow-Credentials : "true"로 응답합니다. 브라우저에서는 이 응답을 통해 통신이 승인되었음을 인지하고 크로스 오리진 액세스를 허용합니다.
여러 오리진에 대한 액세스 권한을 부여하려면 쉼표로 구분된 목록이나 *와 같은 와일드카드 문자를 사용하여 모든 사용자에게 액세스 권한을 부여합니다.
CORS 사전 요청이란 무엇인가요?
HTTP에서 요청 메서드는 클라이언트가 서버를 통해 수행하고자 하는 데이터 작업입니다. 일반적인 HTTP 메서드로는 GET, POST, PUT 및 DELETE가 있습니다.
일반적인 크로스 오리진 리소스 공유(CORS) 상호 작용에서 브라우저는 요청과 액세스 제어 헤더를 동시에 전송합니다. 이러한 요청은 일반적으로 GET 데이터 요청이며 위험이 낮은 것으로 간주됩니다.
그러나 일부 HTTP 요청은 복잡한 것으로 간주되기 때문에 실제 요청을 보내기 전에 서버 확인이 필요합니다. 이 사전 승인 프로세스를 사전 요청이라고 합니다.
복잡한 크로스 오리진 요청
크로스 오리진 요청에 다음 중 하나가 사용되는 경우 이 요청은 복잡한 요청입니다.
- GET, POST 또는 HEAD 외의 메서드
- Accept-Language, Accept 또는 Content-Language 외의 헤더
- multipart/form-data, application/x-www-form-urlencoded 또는 text/plain 외의 Content-Type 헤더
예를 들어 기존 데이터를 삭제하거나 수정하라는 요청은 복잡한 것으로 간주됩니다.
사전 요청 작동 방식
사전 요청이 필요한 경우 브라우저에서 사전 요청이 생성됩니다. 이 요청은 다음과 같은 OPTIONS 요청입니다.
OPTIONS /data HTTP/1.1 Origin: https://example.com Access-Control-Request-Method: DELETE |
브라우저는 실제 요청 메시지 전에 사전 요청을 보냅니다. 서버는 서버가 클라이언트 URL에서 수락할 의향이 있는 크로스 오리진 요청에 대한 정보를 사용하여 사전 요청에 응답해야 합니다. 서버 응답 헤더에는 다음이 포함되어야 합니다.
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
아래에 서버 응답의 예가 나와 있습니다.
HTTP/1.1 200 OK Access-Control-Allow-Headers: Content-Type Access-Control-Allow-Origin: https://news.example.com Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS |
사전 요청 응답에는 경우에 따라 Access-Control-Max-Age 헤더가 추가로 포함됩니다. 이 지표는 브라우저에서 브라우저의 사전 요청 결과를 캐시하는 기간(초)을 지정합니다. 캐싱을 사용하면 브라우저에서 사전 요청 사이에 여러 복잡한 요청을 전송할 수 있습니다. max-age로 지정된 시간이 경과하기 전까지는 다른 사전 요청을 보내지 않아도 됩니다.
CORS와 JSONP의 차이점은 무엇인가요?
JSON with Padding(JSONP)은 서로 다른 도메인에서 실행되는 웹 애플리케이션 간의 통신을 가능하게 하는 기존 기술입니다.
JSONP를 사용하면 클라이언트 페이지에서 HTML 스크립트 태그를 사용할 수 있습니다. 스크립트 태그는 외부 JavaScript 파일을 로드하거나 HTML 페이지에 JavaScript 코드를 직접 임베드합니다. 스크립트에는 동일 오리진 정책이 적용되지 않으므로 JavaScript 코드를 통해 크로스 오리진 데이터를 검색할 수 있습니다.
그러나 데이터는 JSON 형식이어야 합니다. 또한 JSONP는 외부 도메인의 신뢰성에 의존하여 안전한 데이터를 제공하기 때문에 크로스 오리진 리소스 공유(CORS)보다 덜 안전합니다.
현대적인 브라우저에는 몇 가지 보안 기능이 추가되었기 때문에 JSONP가 포함된 오래된 코드는 더 이상 작동하지 않습니다. CORS는 크로스 오리진 액세스 제어를 위한 최신 글로벌 웹 표준입니다.
CORS 모범 사례로는 어떤 것이 있나요?
서버에 크로스 오리진 리소스 공유(CORS) 를 구성할 때는 다음 사항에 유의해야 합니다.
적절한 액세스 목록 정의
쉼표로 구분된 목록을 사용하여 개별 도메인에 대한 액세스 권한을 부여하는 것이 항상 가장 좋습니다. API를 공개하려는 경우가 아니라면 와일드카드를 사용하지 마세요. 그렇지 않을 경우 와일드카드와 정규식을 사용하면 취약성이 발생할 수 있습니다.
예를 들어 접미사 permitted-website.com이 붙은 모든 사이트에 대한 액세스 권한을 부여하는 정규식을 작성한다고 가정해 보겠습니다. 식 하나를 사용하여 api.permitted-website.com과 news.permitted-website.com에 대한 액세스 권한을 부여합니다. 그런데 maliciouspermitted-website.com과 같은 도메인을 사용하는 불법 사이트에 대한 액세스 권한을 실수로 부여합니다.
목록에서 null 오리진 사용 방지
일부 브라우저는 파일 요청 또는 로컬 호스트의 요청과 같은 특정 시나리오에서 요청 헤더에 null 값을 전송합니다.
하지만 액세스 목록에 null 값을 포함하면 안 됩니다. null 헤더가 포함된 무단 요청에 액세스 권한이 부여될 수 있으므로 보안 위험이 발생할 수 있습니다.
AWS는 CORS 요구 사항을 어떻게 지원할 수 있나요?
대부분의 서비스는 크로스 오리진 리소스 공유(CORS)를 기본적으로 지원합니다. 따라서 Amazon Web Services(AWS)에서 호스팅되는 API 및 리소스에 대한 크로스 오리진 액세스를 제어할 수 있습니다.
다음은 CORS를 지원하는 몇 가지 AWS 서비스입니다.
- Amazon Simple Storage Service (S3)는 모든 데이터 스토리지 사용 사례에 적합한 비용 효율적인 스토리지 클래스를 갖춘 객체 스토리지 서비스입니다. Amazon S3를 사용하면 S3 데이터 액세스를 허용할 오리진, 각 오리진에 대해 지원할 작업(HTTP 메서드) 및 기타 작업별 정보를 식별하는 규칙이 포함된 CORS 구성 문서를 만들 수 있습니다. 이 구성에 최대 100개의 규칙을 추가할 수 있습니다.
- Amazon API Gateway는 어떤 규모에서든 API를 손쉽게 생성, 게시, 유지 관리, 모니터링 및 보안 유지할 수 있도록 하는 완전관리형 서비스입니다. Amazon API Gateway 콘솔에서 클릭 한 번으로 직접 REST API에 CORS를 사용하도록 설정할 수 있습니다.
지금 계정을 만들어 AWS에서 API를 시작하세요.