HTTPQUERY
한국어

Access-Control-Allow-Origin

사용법

참고

CORS(Cross-Origin Resource Sharing)는 서버가 명시적으로 접근을 허용하지 않는 한, 웹 페이지가 다른 오리진이 제공한 응답을 읽지 못하게 막는 브라우저 메커니즘입니다. 브라우저는 교차 출처 요청에 Origin 헤더를 자동으로 설정합니다. JavaScript는 Origin 헤더를 수정할 수 없습니다.

모든 CORS 응답은 특정 오리진의 프런트엔드 코드가 응답을 읽어도 되는지 브라우저에 알리기 위해 Access-Control-Allow-Origin을 포함합니다. 일치하는 값이 없으면 브라우저는 응답이 JavaScript에 도달하지 못하도록 차단합니다.

접근을 허용하기로 한 서버에는 세 가지 선택지가 있습니다. 와일드카드, 명시적 오리진, null입니다. 대부분의 운영 API는 들어오는 Origin 요청 헤더를 허용 목록과 대조하여 오리진을 동적으로 선택합니다. 오리진이 일치하면 서버는 그 값을 그대로 돌려줍니다. 요청에 따라 응답이 달라지므로, 캐시가 오리진별로 별도의 사본을 저장하도록 Vary: Origin 헤더가 필요합니다.

CORS를 유발하는 것

다른 오리진으로 가는 모든 fetch()나 XMLHttpRequest는 CORS 적용을 유발합니다. @font-face를 통한 폰트 로딩, WebGL 텍스처, 교차 출처 이미지에 대한 canvas.drawImage()도 CORS 검사를 유발합니다. 커스텀 헤더를 실은 요청, PUT·DELETE·PATCH처럼 단순하지 않은 메서드, 또는 application/json Content-Type을 쓰는 요청은 실제 요청에 앞서 사전 요청 OPTIONS를 유발합니다. 링크를 클릭하거나 브라우저에서 페이지를 로드하는 일반적인 내비게이션은 CORS를 유발하지 않습니다.

* (와일드카드)

모든 오리진이 응답을 읽도록 허용합니다. 와일드카드는 자격 증명이 없는 요청에만 유효합니다.

Access-Control-Allow-Origin: *

참고

와일드카드는 자격 증명이 포함된 요청과 호환되지 않습니다. Access-Control-Allow-Credentials가 true일 때 서버는 명시적인 오리진을 반환해야 합니다.

명시적 오리진

스킴, 호스트명, 선택적 포트로 구성된 단일 오리진 값입니다. 알려진 호출자로 제한된 API에서 쓰이는 표준적인 방식입니다.

Access-Control-Allow-Origin: https://example.com

응답당 하나의 오리진만 허용됩니다. 여러 오리진을 지원하는 서버는 Origin 요청 헤더를 살펴 일치한 값으로 응답하고, 응답에 Vary: Origin을 추가합니다.

null

불투명하거나 개인정보에 민감한 오리진을 나타냅니다. 일부 샌드박스 문서와 로컬 파일 URL은 자신의 오리진으로 null을 보냅니다.

Access-Control-Allow-Origin: null

참고

null로 응답하는 것은 권장되지 않습니다. 샌드박스 iframe의 악의적인 문서도 null 오리진을 가지므로 이 값은 위조하기 쉽습니다.

예시

서버가 요청한 오리진을 동적으로 그대로 돌려주고, 올바른 캐시 동작을 위해 Vary 헤더를 포함합니다.

Access-Control-Allow-Origin: https://example.com
Vary: Origin

모든 호출자에게 정적 애셋을 제공하는 공개 CDN은 와일드카드를 사용합니다.

Access-Control-Allow-Origin: *

자격 증명이 포함된 교차 출처 응답은 명시적인 오리진과 자격 증명 헤더를 함께 담습니다.

Access-Control-Allow-Origin: https://dashboard.example.re
Access-Control-Allow-Credentials: true
Vary: Origin

문제 해결

브라우저가 응답의 오리진을 요청한 페이지와 대조하지 못하면 교차 출처 요청이 실패합니다.

콘솔에 “No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”가 표시됩니다. 서버가 헤더를 전혀 포함하지 않은 것입니다. 서버 측 CORS 설정이 해당 라우트와 HTTP 메서드에 적용되는지 확인하십시오. nginx에서는 add_header 디렉티브가 올바른 location 블록 안에 있는지 확인하십시오. Apache에서는 Header set이 일치하는 나 안에 있는지 확인하십시오. 브라우저 동작과 문제를 분리하려면 curl로 테스트하십시오. curl -v -H “Origin: https://example.com” https://api.example.re/data

자격 증명이 포함된 요청에서 와일드카드 *가 동작하지 않습니다. 브라우저는 Access-Control-Allow-Origin: * 와 Access-Control-Allow-Credentials: true 를 함께 쓴 응답을 거부합니다. 해결책은 들어오는 Origin 헤더를 읽어 허용 목록과 대조해 검증하고, 일치한 오리진을 그대로 돌려주는 것입니다. 캐시가 오리진별로 별도의 사본을 저장하도록 응답에 Vary: Origin을 추가하십시오.

검증 없는 Origin 반사. 허용 목록을 확인하지 않고 Origin 요청 헤더를 그대로 되돌려 주면 API가 어떤 도메인에나 열립니다. 공격자는 자신이 통제하는 페이지를 통해 데이터를 훔치는 데 이를 악용합니다. 반사하기 전에 들어오는 오리진을 반드시 신뢰할 수 있는 값 목록과 대조하십시오.

CDN이 잘못된 오리진으로 응답을 캐시합니다. 서버가 동적인 오리진 값을 반환하면서 Vary: Origin을 생략하면, CDN은 첫 번째 오리진 값을 저장한 뒤 이후의 모든 오리진에 같은 캐시 응답을 제공합니다. 동적인 오리진을 반영하는 모든 응답에 Vary: Origin을 추가하십시오. Cloudflare에서는 CORS 관리형 변환을 사용할 때 이것이 자동으로 처리됩니다. 다른 CDN에서는 오리진이 캐시 키에 포함되는지 확인하십시오.

사전 요청은 성공하는데 실제 요청이 실패합니다. OPTIONS 응답에는 CORS 헤더가 있지만 뒤따르는 GET, POST, PUT 응답에는 없는 경우입니다. 많은 서버 프레임워크가 OPTIONS를 다른 메서드와 별도로 처리합니다. CORS 헤더가 사전 요청 응답에만이 아니라 모든 유형의 응답에 추가되도록 하십시오. Express에서는 모든 응답이 미들웨어를 거치도록 라우트 핸들러보다 앞에 CORS 미들웨어를 두십시오.

curl로는 헤더가 올바른데 브라우저는 여전히 차단합니다. DevTools를 열고 Network 탭으로 가서 브라우저가 실제로 받은 응답 헤더를 살펴보십시오. 프록시, 로드 밸런서, CDN 엣지 규칙이 오리진 서버와 브라우저 사이에서 CORS 헤더를 제거하거나 덮어쓰는 경우가 있습니다. curl 출력과 DevTools 출력을 비교하여 헤더를 없애는 계층을 찾아내십시오.