교차 출처 리소스 공유, 웹 브라우저에서 실행되는 JavaScript가 다른 도메인(Origin)에 있는 리소스에 접근할 수 있는 권한을 부여하기 위한 메커니즘이다.
ex: https://domain-a.com
의 프론트 엔드 JavaScript 코드가 XMLHttpRequest
를 사용하여 https://domain-b.com/data.json
을 요청하는 경우
웹 애플리케이션은 보안 상의 이유로 동일 출처 정책(Same-Origin Policy, SOP)에 의해 제한되어 있어, 스크립트가 다른 도메인으로부터 리소스를 요청하는 것은 기본적으로 금지된다. CORS는 웹 애플리케이션에서 보다 유연한 데이터 교환과 API 호출을 가능하게 하기 위해 SOP를 확장하는 개념.
2011년, RFC 6454에서 처음 등장한 보안 정책. 웹 보안 메커니즘 중 하나로, 웹 브라우저에서 실행되는 JavaScript를 통해 로드된 문서나 스크립트가 동일한 출처(Origin)로부터 로드된 리소스와만 상호작용할 수 있도록 제한하는 정책.
CORS는 SOP을 우회하기 위한 메커니즘 중 하나.
서버의 위치를 의미하는 https://google.com
과 같은 URL들은 마치 하나의 문자열 같아 보여도, 사실은 여러 개의 구성 요소로 이루어져 있음.
출처는 프로토콜(ex: HTTP, HTTPS), 호스트(도메인) 이름, 포트 번호의 조합을 의미. 출처 내의 포트 번호는 생략이 가능한데, 이는 각 웹에서 사용하는 HTTP, HTTPS 프로토콜의 기본 포트 번호가 정해져있기 때문.
http://store.company.com/dir/page.html
의 출처를 비교한 예시
URL | 결과 | 이유 |
---|---|---|
http://store.company.com/dir2/other.html | 성공 | 경로만 다름 |
http://store.company.com/dir/inner/another.html | 성공 | 경로만 다름 |
https://store.company.com/secure.html | 실패 | 프로토콜 다름 |
http://store.company.com:81/dir/etc.html | 실패 | 포트 다름 (http://는 80이 기본값) |
http://news.company.com/dir/other.html | 실패 | 호스트 다름 |
교차 출처 공유 표준 참고.
XMLHttpRequest
와 Fetch API
호출@font-face
에서 교차 도메인 폰트 사용 시)drawImage()
를 사용해 캔버스에 그린 이미지/비디오 프레임Origin: https://velog.io/@chocoallergie
GET
을 제외한 HTTP 메서드)에 대해서는 CORS 명세에서 브라우저가 사전 전달(preflight)라고 하는 OPTIONS
메서드를 사용하여 서버가 요청을 처리할 수 있는지 확인하고 허용된 출처인지 확인.예시
https://foo.example
의 웹 컨텐츠가 https://bar.other
도메인의 컨텐츠를 호출하길 원한다. foo.example
에 배포된 자바스크립트에는 아래와 같은 코드가 사용된다.
const xhr = new XMLHttpRequest();
const url = 'https://bar.other/resources/public-data/';
xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();
클라이언트와 서버간에 간단한 통신을 하고, CORS 헤더를 사용하여 권한을 처리함.
브라우저가 서버로 전송하는 내용을 살펴보고, 서버의 응답을 확인함.
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
요청 헤더의 Origin
을 보면, https://foo.example
로부터 요청이 왔다는 것을 알 수 있음.
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
[…XML Data…]
Access-Control-Allow-Origin
헤더를 다시 전송Access-Control-Allow-Origin: *,
으로 응답다음엔 사전 전달에 대해 블로깅!