XMLHttpRequest가 XXX No 'Access-Control-Allow-Origin'헤더를로드 할 수 없습니다.

Feb 22 2016

tl; dr; 동일 원산지 정책 정보

express.js 서버의 인스턴스를 시작하는 Grunt 프로세스가 있습니다. 이것은 Chrome (최신 버전)의 개발자 콘솔에있는 오류 로그에 다음과 같은 내용이 표시되는 빈 페이지를 제공하기 시작했을 때까지 완벽하게 작동했습니다.

XMLHttpRequest에서 https://www.example.com/을 로드 할 수 없습니다 . 요청 된 리소스에 'Access-Control-Allow-Origin'헤더가 없습니다. 따라서 원본 ' http : // localhost : 4300 '은 액세스가 허용되지 않습니다.

페이지에 액세스하지 못하게하는 이유는 무엇입니까?

답변

224 Quentin Feb 22 2016 at 19:26

tl; dr — 관련 부분을 더 쉽게 찾을 수 있도록 끝에 요약과 답변 제목이 있습니다. 모든 것을 읽는 것이 다른 상황에서 어떻게 적용 되는지 더 쉽게 볼 수있는 이유 를 이해하는 데 유용한 배경을 제공하기 때문에 권장 됩니다.

동일 원산지 정책 정보

이것은 동일 출처 정책 입니다. 브라우저에 의해 구현 된 보안 기능입니다.

당신의 특별한 경우는이 XMLHttpRequest를 구현하는 방법을 보여주고있다 (그리고 당신이 패치를 사용한다면 당신은 동일한 결과를 얻을 수 있습니다)뿐만 아니라 (예에로드 된 이미지와 같은 다른 것들에 적용 <canvas>에로드 또는 문서 <iframe>단지와 함께) 약간 다른 구현입니다.

(이상하게도 CSS 글꼴에도 적용되지만 발견 된 파운드리가 동일 출처 정책이 일반적으로 다루는 보안 문제가 아닌 DRM을 주장했기 때문입니다.)

SOP의 필요성을 보여주는 표준 시나리오는 세 문자 로 설명 할 수 있습니다 .

  • Alice는 웹 브라우저를 가진 사람입니다.
  • Bob은 웹 사이트를 실행합니다 ( https://www.[website].com/예 :
  • Mallory는 웹 사이트를 실행합니다 ( http://localhost:4300귀하의 예에서)

Alice는 Bob의 사이트에 로그인하고 일부 기밀 데이터를 가지고 있습니다. 아마도 회사 인트라넷 (LAN의 브라우저에서만 액세스 가능) 또는 온라인 뱅킹 (사용자 이름과 비밀번호를 입력 한 후 얻은 쿠키로만 액세스 가능) 일 수 있습니다.

Alice는 Alice의 브라우저가 Bob의 웹 사이트 (쿠키가있는 IP 주소 등)에 HTTP 요청을하게하는 JavaScript가있는 Mallory의 웹 사이트를 방문합니다. 이것은 사용하는 등 간단하게 할 수 XMLHttpRequest와 읽기 responseText.

브라우저의 동일 출처 정책은 JavaScript가 Bob의 웹 사이트 (Bob과 Alice가 Mallory가 액세스하는 것을 원하지 않음)에서 반환 한 데이터를 읽지 못하도록합니다. 당신은, 예를 들어, 사용하여 이미지를 표시 할 수있는 (주 <img>이미지의 내용이) 자바 스크립트 (또는 말로리에 노출되지 않기 때문에 당신이이 경우에 믹스로 캔버스 던져하지 않는 한 ... 기원에 걸쳐 요소를 합니다 동일 기원을 생성을 위반 오류).


같은 원산지 정책이 필요하지 않다고 생각할 때 적용되는 이유

주어진 URL에 대해 SOP가 필요하지 않을 수 있습니다. 이러한 경우 몇 가지 일반적인 시나리오는 다음과 같습니다.

  • Alice, Bob, Mallory는 같은 사람입니다.
  • Bob은 전적으로 공개 정보를 제공합니다.

… 그러나 브라우저는 위 중 하나가 사실인지 알 수있는 방법이 없으므로 신뢰는 자동이 아니며 SOP가 적용됩니다. 브라우저가 다른 웹 사이트에 제공된 데이터를 제공하기 전에 명시 적으로 권한을 부여해야합니다.


동일한 출처 정책이 웹 페이지의 JavaScript에만 적용되는 이유

브라우저 확장 *, 브라우저 개발자 도구의 네트워크 탭 및 Postman과 같은 응용 프로그램이 설치된 소프트웨어입니다. 다른 웹 사이트 를 방문했기 때문에 한 웹 사이트에서 다른 웹 사이트에 속한 자바 스크립트로 데이터를 전달하지 않습니다 . 소프트웨어를 설치하려면 일반적으로보다 의식적인 선택이 필요합니다.

위험으로 간주되는 제 3 자 (몰 로리)가 없습니다.

*출처 간 문제를 방지하려면 브라우저 확장을 신중하게 작성해야합니다. 예를 들어 Chrome 문서를 참조하십시오 .


JS로 읽지 않고 페이지에 데이터를 표시 할 수있는 이유

Mallory의 사이트로 인해 브라우저가 제 3 자로부터 데이터를 가져와 표시 할 수있는 여러 상황이 있습니다 (예 : <img>이미지를 표시하는 요소 추가 ). 그러나 Mallory의 JavaScript가 해당 리소스의 데이터를 읽을 수는 없지만 Alice의 브라우저와 Bob의 서버 만 그렇게 할 수 있으므로 여전히 안전합니다.


CORS

오류 메시지에 언급 된 Access-Control-Allow-OriginHTTP 응답 헤더는 CORS 표준의 일부로 Bob이 Mallory의 사이트에 Alice의 브라우저를 통해 데이터에 액세스 할 수있는 권한을 명시 적으로 부여 할 수 있습니다.

기본 구현에는 다음이 포함됩니다.

Access-Control-Allow-Origin: *

… 모든 웹 사이트에서 데이터를 읽을 수 있도록 응답 헤더에서.

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

… 특정 사이트 만 액세스하도록 허용하고 Bob은 Origin 요청 헤더를 기반으로 동적으로 생성하여 모든 사이트가 아닌 여러 사이트에서 액세스하도록 허용 할 수 있습니다.

Bob이 해당 응답 헤더를 설정하는 방법에 대한 세부 사항은 Bob의 HTTP 서버 및 / 또는 서버 측 프로그래밍 언어에 따라 다릅니다. 이 다양한 일반적인 구성을위한 가이드의 모음 그 힘의 도움.

NB : 일부 요청은 복잡하며 브라우저가 JS가 원하는 GET / POST / PUT / Whatever 요청을 보내기 전에 서버가 응답해야하는 프리 플라이트 OPTIONS 요청을 보냅니다. Access-Control-Allow-Origin특정 URL 에만 추가 되는 CORS 구현은 종종 이로 인해 실패합니다.


분명히 CORS를 통해 권한을 부여하는 것은 Bob이 다음과 같은 경우에만 수행 할 수있는 작업입니다.

  • 데이터가 비공개가 아니 거나
  • 말로리는 신뢰 받았다

하지만 저는 밥이 아닙니다!

Mallory 가 제어하지 않는 Bob의 웹 사이트에서 가져와야 하기 때문에이 헤더를 추가하는 표준 메커니즘 이 없습니다.

Bob이 공용 API를 실행하는 경우 CORS를 켜는 메커니즘이있을 수 있습니다 (예 : 특정 방식으로 요청을 형식화하거나 Bob의 사이트에 대한 개발자 포털 사이트에 로그인 한 후 구성 옵션). 이것은 Bob이 구현 한 메커니즘이어야합니다. Mallory는 Bob의 사이트에있는 문서를 읽고 사용 가능한 것이 있는지 확인하거나 Bob과 대화하여 CORS를 구현하도록 요청할 수 있습니다.


"프리 플라이트에 대한 응답"을 언급하는 오류 메시지

일부 교차 오리진 요청은 프리 플라이트 됩니다.

이것은 (대략적으로 말하면) 다음과 같은 교차 출처 요청을하려고 할 때 발생합니다.

  • 쿠키와 같은 자격 증명 포함
  • 일반 HTML 양식으로 생성 할 수 없습니다 (예 : 양식의에서 사용할 수없는 사용자 정의 헤더 또는 Content-Type 포함 enctype).

프리 플라이트가 필요한 작업을 올바르게 수행하고있는 경우

이러한 경우에 다음 이 답변의 나머지 부분은 계속 적용 하지만 당신은 또한 서버가 될 것이다 (프리 플라이트 요청을 수신 할 수 있는지 확인해야합니다 OPTIONS(그리고 GET, POST또는 오른쪽으로에 보내려고) 및 응답했다 어떤 Access-Control-Allow-Origin헤더뿐만 아니라 Access-Control-Allow-MethodsAccess-Control-Allow-Headers특정의 HTTP 메소드 또는 헤더를 허용합니다.

실수로 프리 플라이트를 트리거하는 경우

때때로 사람들은 Ajax 요청을 구성하려고 할 때 실수를하고, 때때로 이로 인해 프리 플라이트가 필요합니다. API가 원본 간 요청을 허용하도록 설계되었지만 프리 플라이트가 필요한 항목이 필요하지 않은 경우 액세스가 중단 될 수 있습니다.

이를 유발하는 일반적인 실수는 다음과 같습니다.

  • Access-Control-Allow-Origin요청에 다른 CORS 응답 헤더 를 넣으려고합니다 . 이는 요청에 속하지 않으며 도움이되는 작업을 수행하지 않으며 (자신에게 권한을 부여 할 수있는 권한 시스템의 요점은 무엇입니까?) 응답에만 나타나야합니다.
  • 풋 시도 Content-Type: application/json(일반적으로 때 저자 혼란의 내용을 설명 할 요청 본문이없는 GET 요청에 헤더 Content-TypeAccept).

이 두 경우 모두 추가 요청 헤더를 제거하면 프리 플라이트 (단순 요청을 지원하지만 프리 플라이트 요청이 아닌 API와 통신 할 때 문제가 해결됨)가 필요하지 않을 수 있습니다.


불투명 한 응답

때때로 HTTP 요청을해야하지만 응답을 읽을 필요가 없습니다. 예를 들어 기록을 위해 서버에 로그 메시지를 게시하는 경우.

당신이 사용하는 경우 API (아닌를 ), 당신은 그것을 사용 CORS 시도하지 구성 할 수 있습니다.fetchXMLHttpRequest

이것은 CORS에 필요한 작업을 수행하도록 허용하지 않습니다. 응답을 읽을 수 없습니다. 프리 플라이트가 필요한 요청을 할 수 없습니다.

간단한 요청을하고 응답을 보지 않고 개발자 콘솔에 오류 메시지를 채우지 않도록합니다.

이를 수행하는 방법은 fetchCORS를 사용하여 응답을 볼 수있는 권한이없는 요청을 할 때 제공되는 Chrome 오류 메시지에 의해 설명됩니다 .

CORS 정책에 의해 https://example.com/' https://example.net' 출처 ' '에서 가져 오기에 대한 액세스 가 차단되었습니다 Access-Control-Allow-Origin. 요청 된 리소스에 ' '헤더가 없습니다 . 불투명 한 응답이 요구 사항을 충족하는 경우 요청 모드를 'no-cors'로 설정하여 CORS가 비활성화 된 리소스를 가져옵니다.

그러므로:

fetch("http://example.com", { mode: "no-cors" });

CORS의 대안

JSONP

Bob은 CORS가 나오기 전에 사람들이 Ajax를 교차 출처로 만든 방법 인 JSONP 와 같은 해킹을 사용하여 데이터를 제공 할 수도 있습니다 .

그것은 Mallory의 페이지에 데이터를 주입하는 JavaScript 프로그램의 형태로 데이터를 제시함으로써 작동합니다.

Mallory는 Bob이 악성 코드를 제공하지 않도록 신뢰해야합니다.

공통 주제에 유의하십시오. 데이터를 제공하는 사이트는 제 3 자 사이트가 브라우저로 보내는 데이터에 액세스하는 것이 괜찮다는 것을 브라우저에 알려야합니다.

JSONP는 <script>페이지에 이미있는 함수를 호출하는 JavaScript 프로그램의 형태로 데이터를로드 하는 요소를 추가하는 방식으로 작동하므로 JSON을 반환하는 URL에서 JSONP 기술을 사용하려고하면 실패 (일반적으로 CORB 오류)가 발생합니다. JavaScript가 아닙니다.

두 리소스를 단일 Origin으로 이동

JS가 실행되는 HTML 문서와 요청되는 URL이 동일한 출처 (동일한 체계, 호스트 이름 및 포트 공유)에있는 경우 동일한 출처 정책이 기본적으로 권한을 부여합니다. CORS는 필요하지 않습니다.

프록시

Mallory 서버 측 코드를 사용하여 데이터를 가져올 수 있습니다 (그런 다음 평소와 같이 HTTP를 통해 서버에서 Alice의 브라우저로 전달할 수 있음).

다음 중 하나입니다.

  • CORS 헤더 추가
  • 응답을 JSONP로 변환
  • HTML 문서와 동일한 출처에 존재

해당 서버 측 코드는 CORS Anywhere와 같은 제 3 자에 의해 작성 및 호스팅 될 수 있습니다. 이것의 프라이버시 의미에 유의하십시오. 타사는 서버에서 누가 무엇을 프록시하는지 모니터링 할 수 있습니다.

Bob은이를 위해 어떤 권한도 부여 할 필요가 없습니다.

Mallory와 Bob 사이에 있기 때문에 여기에는 보안 의미가 없습니다. Bob이 Mallory가 Alice라고 생각하고 Alice와 Bob간에 기밀로 유지되어야하는 데이터를 Mallory에 제공 할 방법이 없습니다.

따라서 Mallory는이 기술을 사용하여 공용 데이터 를 읽을 수만 있습니다 .

그러나 다른 사람의 웹 사이트에서 콘텐츠를 가져 와서 직접 표시하는 것은 저작권침해 하고 법적 조치를 취할 수 있다는 점에 유의하세요 .

웹 앱 이외의 내용 작성

"동일한 출처 정책이 웹 페이지의 JavaScript에만 적용되는 이유"섹션에서 언급했듯이 웹 페이지에 JavaScript를 작성하지 않으면 SOP를 피할 수 있습니다.

그렇다고 JavaScript와 HTML을 계속 사용할 수 없다는 의미는 아니지만 Node-WebKit 또는 PhoneGap과 같은 다른 메커니즘을 사용하여 배포 할 수 있습니다.

브라우저 확장

동일한 출처 정책이 적용되기 전에 브라우저 확장이 응답에 CORS 헤더를 삽입 할 수 있습니다.

이는 개발에 유용 할 수 있지만 프로덕션 사이트에는 실용적이지 않습니다 (사이트의 모든 사용자에게 브라우저의 보안 기능을 비활성화하는 브라우저 확장 프로그램을 설치하도록 요청하는 것은 불합리합니다).

또한 간단한 요청으로 만 작동하는 경향이 있습니다 (프리 플라이트 OPTIONS 요청을 처리 할 때 실패 함).

로컬 개발 서버 가 있는 적절한 개발 환경을 갖는 것이 일반적으로 더 나은 접근 방식입니다.


기타 보안 위험

SOP / CORS는 독립적으로 처리해야하는 XSS , CSRF 또는 SQL 주입 공격을 완화하지 않습니다 .


요약

  • 당신이 할 수있는 일은 없다 당신의 사람에게 CORS 액세스를 가능하게 할 것이다 클라이언트 측 코드를 다른 사람의 서버.
  • 서버를 제어하는 ​​경우 요청이 이루어집니다. CORS 권한을 추가합니다.
  • 제어하는 사람과 친한 경우 : CORS 권한을 추가하도록 요청하십시오.
  • 공공 서비스 인 경우 :
    • API 문서를 읽고 클라이언트 측 JavaScript로 액세스하는 방법에 대해 설명합니다.
      • 특정 URL을 사용하라고 말할 수 있습니다.
      • JSONP를 지원할 수 있습니다.
      • 클라이언트 측 코드에서 교차 출처 액세스를 전혀 지원하지 않을 수 있습니다 (특히 각 요청에서 개인화 된 API 키를 전달해야하는 경우 보안 근거에 대한 의도적 인 결정일 수 있음).
    • 필요하지 않은 프리 플라이트 요청을 트리거하지 않았는지 확인하십시오. API는 단순 요청에 대한 권한을 부여 할 수 있지만 프리 플라이트 요청에는 허용하지 않을 수 있습니다.
  • 위의 어느 것도 적용되지 않는 경우 : 브라우저가 대신 서버와 통신하도록 한 다음 서버가 다른 서버에서 데이터를 가져와 전달하도록합니다. (사용할 수있는 공개적으로 액세스 할 수있는 리소스에 CORS 헤더를 첨부하는 타사 호스팅 서비스도 있습니다.)
4 Daphoque Sep 09 2016 at 17:45

대상 서버는 원본 간 요청을 허용해야합니다. 익스프레스를 통해 허용하려면 http 옵션 요청을 처리하기 만하면됩니다.

app.options('/url...', function(req, res, next){
   res.header('Access-Control-Allow-Origin', "*");
   res.header('Access-Control-Allow-Methods', 'POST');
   res.header("Access-Control-Allow-Headers", "accept, content-type");
   res.header("Access-Control-Max-Age", "1728000");
   return res.sendStatus(200);
});
3 zwif Nov 09 2017 at 18:37

이것은 허용 된 답변에 언급되어 있지 않습니다.

  • 이 정확한 질문에는 해당되지 않지만 해당 문제를 검색하는 다른 사용자에게 도움이 될 수 있습니다.
  • 이것은 경우에 따라 CORS 오류를 방지하기 위해 클라이언트 코드에서 수행 할 수있는 작업입니다 .

단순 요청 을 사용할 수 있습니다 .
'단순 요청'을 수행하려면 요청이 여러 조건을 충족해야합니다. 예를 들어 POST, GETHEAD메서드 만 허용하고 일부 지정된 헤더 만 허용합니다 ( 여기에서 모든 조건을 찾을 수 있음 ).

클라이언트 코드가하는 경우 명시 적 설정은 헤더의 영향을받지 않습니다 (예 : "승인")가 요청에 수정 값을 수있는 몇 가지 클라이언트가 어떤 "표준이 아닌"값으로 이용 약관을 읽고 동의에 서버를 일으키는 원인이 자동으로 이러한 헤더를 설정하는 것을 발생 Simple Request-CORS 오류가 발생합니다.

2 Vishnu Feb 22 2016 at 19:32

이것은 CORS 오류로 인해 발생합니다. CORS는 Cross Origin Resource Sharing의 약자입니다. 간단히 말해서이 오류는 다른 도메인에서 도메인 / 리소스에 액세스하려고 할 때 발생합니다.

여기에 대한 자세한 내용 : jquery의 CORS 오류

이 문제를 해결하려면 다른 도메인에 대한 액세스 권한이있는 경우 서버에서 Access-Control-Allow-Origin을 허용해야합니다. 이것은 헤더에 추가 할 수 있습니다. 모든 요청 / 도메인 또는 특정 도메인에 대해이를 활성화 할 수 있습니다.

CORS (Cross-Origin Resource Sharing) 요청 후 작업을 가져 오는 방법

이 링크는 도움이 될 수 있습니다.

morph85 Dec 17 2018 at 13:40

이 CORS 문제는 다른 원인에 대해 더 자세히 설명되지 않았습니다.

현재 다른 이유로이 문제가 발생합니다. 내 프런트 엔드는 'Access-Control-Allow-Origin'헤더 오류도 반환합니다.

이 헤더가 제대로 반영되지 않았기 때문에 잘못된 URL을 가리켰다는 것뿐입니다. localhost (프런트 엔드)-> 보안되지 않은 http (https로 가정)에 대한 호출, 프런트 엔드의 API 엔드 포인트가 올바른 프로토콜을 가리키는 지 확인하십시오.

Subhashi Feb 11 2020 at 18:02

Chrome 콘솔에서 동일한 오류가 발생했습니다.

내 문제는 http://대신을 사용하여 사이트로 이동하려고했습니다 https://. 따라서 수정할 것이 없었으며 .NET을 사용하여 동일한 사이트로 이동해야했습니다 https.

HungNM2 Aug 20 2020 at 09:13

이 버그는 2 일이 소요되었습니다. 내 서버 로그를 확인했는데 브라우저 Chrome / Edge와 서버 간의 Preflight 옵션 요청 / 응답이 정상이었습니다. 주된 이유는 XHTMLRequest에 대한 GET / POST / PUT / DELETE 서버 응답 에도 다음 헤더가 있어야하기 때문입니다.

access-control-allow-origin: origin  

"origin"은 요청 헤더에 있습니다 (브라우저가 요청에 추가합니다). 예를 들면 :

Origin: http://localhost:4221

다음과 같은 응답 헤더를 추가하여 모두 수락 할 수 있습니다.

access-control-allow-origin: *  

또는 다음과 같은 특정 요청에 대한 응답 헤더 :

access-control-allow-origin: http://localhost:4221 

브라우저의 메시지는 "... 요청 된 리소스" 를 이해하기 어렵습니다.

: 참고 CORS가 로컬 호스트에 적합합니다. 다른 포트는 다른 도메인을 의미합니다. 오류 메시지가 나타나면 서버 측에서 CORS 구성을 확인하십시오.