express.js 서버 인스턴스를 시작하는 Grunt 프로세스가 있습니다. 지금까지는 모두 완벽하게 작동했지만 이제 빈 페이지가 제공되기 시작하고 Chrome(최신 버전) 개발자 콘솔의 오류 로그에 다음이 표시됩니다.
XMLHttpRequest는 https://www.example.com/을 로드할 수 없습니다. 요청한 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다. 따라서 'http://localhost:4300'에서의 접속은 허용되지 않습니다.
이 페이지에 액세스하는 것을 차단하는 것은 무엇입니까?
대상 서버는 도메인 간 요청을 허용해야 합니다. Express를 통해 허용하려면 http 옵션 요청을 처리하세요.
으아악tl;dr — (주로) 클라이언트 측 JS를 사용하여 다른 서버에서 데이터를 읽으려면 데이터를 원하는 코드에 명시적인 권한을 부여하기 위해 데이터가 있는 서버가 필요합니다.
관련 부분을 더 쉽게 찾을 수 있도록 답변 끝에 요약과 제목이 있습니다. 하지만 이유를 이해하는 데 유용한 배경 지식을 제공하므로 어떻게가 다양한 상황에서 어떻게 적용되는지 더 쉽게 알 수 있으므로 모든 내용을 읽는 것이 좋습니다.
동일출처 정책에 대하여
이것은 동일 원산지 정책입니다. 브라우저에서 구현한 보안 기능입니다.
귀하의 특별한 사례는 XMLHttpRequest에 대해 구현된 방법을 보여 주며(가져오기를 사용하는 경우 동일한 결과를 얻을 수 있음) 약간 다른 구현을 통해 다른 항목(예:
<canvas>
or documents loaded into an<iframe>
에 로드된 이미지)에도 적용됩니다. .SOP의 필요성을 보여주는 표준 시나리오는 세 글자로 설명할 수 있습니다.
https://www.example.com/
)http://localhost:4300
)Alice는 Bob의 사이트에 로그인했으며 여기에 일부 기밀 데이터가 있습니다. 아마도 회사 인트라넷(LAN의 브라우저에서만 액세스 가능)이거나 온라인 뱅킹(사용자 이름과 비밀번호를 입력한 후 얻는 쿠키를 통해서만 액세스 가능)일 수 있습니다.
Alice는 Alice의 브라우저가 Bob의 웹 사이트(쿠키 등을 사용하여 IP 주소에서)에 HTTP 요청을 하도록 하는 일부 JavaScript가 있는 Mallory의 웹 사이트를 방문합니다.
를 사용하는 것만큼 간단할 수 있습니다.XMLHttpRequest
and reading theresponseText
.브라우저의 동일 출처 정책은 JavaScript가 Bob의 웹사이트(Bob과 Alice가 Mallory가 액세스하는 것을 원하지 않음)에서 반환된 데이터를 읽는 것을 방지합니다. (예를 들어, 이미지의 내용이 JavaScript(또는 Mallory)에 노출되지 않기 때문에 원본 전반에 걸쳐
동일 출처 정책이 적용되어서는 안 된다고 생각하는데 왜 적용되나요<img>
요소를 사용하여 이미지를 표시할 수 있습니다. 캔버스를 믹스에 넣지 않는 한 동일 출처 위반 오류).어떤 URL이든 SOP가 필요하지 않을 수 있습니다. 이러한 경우에 대한 몇 가지 일반적인 시나리오는 다음과 같습니다.
... 하지만 브라우저는 위의 내용 중 하나라도 사실인지 알 수 없으므로 신뢰가 자동으로 이루어지지 않으며 SOP가 적용됩니다. 브라우저가 Bob으로부터 받은 데이터를 다른 웹사이트에 제공하기 전에 명시적으로 권한을 부여해야 합니다.
동일 출처 정책이 웹 페이지의 JavaScript에 적용되지만 그 외에는 적용되지 않는 이유
웹페이지 외부
브라우저 확장
*
, 브라우저 개발자 도구의 네트워크 탭, Postman과 같은 애플리케이션이 설치된 소프트웨어입니다. 단지 사용자가 다른 웹사이트를 방문했다는 이유만으로 한 웹사이트에서 다른 웹사이트에 속한 JavaScript로 데이터를 전달하는 것이 아닙니다. 소프트웨어 설치에는 일반적으로 좀 더 신중한 선택이 필요합니다.위험으로 간주되는 제3자(말로리)는 없습니다.
*
교차 출처 문제를 방지하려면 브라우저 확장 프로그램을 주의 깊게 작성해야 합니다. 예시를 보려면 Chrome 문서를 참조하세요.웹페이지 내부
대부분의 경우 웹페이지에 내용을 표시하는 것만으로는 정보 유출이 크지 않습니다.
CORS를 통해 요청 권한을 명시적으로 활성화하기 위해
<img>
element to load an image, then it gets shown on the page, but very little information is exposed to Mallory. JavaScript can't read the image (unless you use acrossOrigin
속성을 사용하는 경우) 이를 서버에 복사하세요.그러나 일부 정보는 유출되므로 Google의 Domenic Denicola를 인용하자면:
이것이 원본 간에 글꼴을 로드하려면 CORS 권한이 필요한 이유입니다.
JS를 사용하여 페이지를 읽지 않고도 페이지에 데이터를 표시할 수 있는 이유
Mallory의 사이트로 인해 브라우저가 제3자로부터 데이터를 가져와 표시할 수 있는 상황이 많이 있습니다(예: 이미지를 표시하기 위해
<img>
요소를 추가하는 경우). Mallory의 JavaScript가 해당 리소스의 데이터를 읽는 것은 불가능하지만 Alice의 브라우저와 Bob의 서버만이 이를 읽을 수 있으므로 여전히 안전합니다.CORS
오류 메시지에 언급된
Access-Control-Allow-Origin
HTTP response 헤더는 Bob이 Mallory의 사이트에 Alice의 브라우저를 통해 데이터에 액세스할 수 있는 권한을 명시적으로 부여할 수 있는 CORS 표준의 일부입니다.기본 구현에는 다음이 포함됩니다.
으아악… 응답 헤더에 모든 웹사이트에서 데이터를 읽을 수 있도록 허용합니다.
으아악… 특정 사이트만 액세스하도록 허용하며 Bob은
Origin
request 헤더를 기반으로 이를 동적으로 생성하여 전체가 아닌 여러 사이트의 액세스를 허용할 수 있습니다.Bob이 응답 헤더를 설정하는 구체적인 방법은 Bob의 HTTP 서버 및/또는 서버측 프로그래밍 언어에 따라 다릅니다. Node.js/Express.js 사용자는 잘 문서화된 CORS 미들웨어를 사용해야 합니다. 다른 플랫폼 사용자는 도움이 될 수 있는 다양한 일반 구성에 대한 가이드 모음을 살펴보세요.
NB: 일부 요청은 복잡하며 JS가 원하는 GET/POST/PUT/모든 요청을 브라우저가 보내기 전에 서버가 응답해야 하는 preflight OPTIONS 요청을 보냅니다. 특정 URL에만
Access-Control-Allow-Origin
를 추가하는 CORS 구현은 종종 이로 인해 문제가 발생합니다.CORS를 통해 권한을 부여하는 것은 Bob이 다음 중 하나의 경우에만 수행하는 작업입니다.
이 헤더를 어떻게 추가하나요?
서버 환경에 따라 다릅니다.
가능하다면 모든 것을 수동으로 처리하는 대신 간단한 옵션을 제공하는 CORS를 처리하도록 설계된 라이브러리를 사용하세요.
Enable-Cors.org에는 유용할 수 있는 특정 플랫폼 및 프레임워크에 대한 문서 목록이 있습니다.
하지만 저는 밥이 아닙니다!
이 헤더는 Bob이 제어할 수 없는 웹사이트에서 가져와야 하기 때문에 Mallory가 이 헤더를 추가하는 표준 메커니즘이 없습니다.
Bob이 공개 API를 실행 중인 경우 CORS를 활성화하는 메커니즘이 있을 수 있습니다(특정 방식으로 요청 형식을 지정하거나 Bob 사이트의 개발자 포털 사이트에 로그인한 후 구성 옵션을 통해). 하지만 이는 Bob이 구현한 메커니즘이어야 합니다. Mallory는 Bob의 사이트에 있는 문서를 읽어서 사용 가능한 항목이 있는지 확인하거나 Bob에게 CORS 구현을 요청할 수 있습니다.
"비행 전 응답"을 언급하는 오류 메시지
일부 교차 출처 요청은 사전 실행됩니다.
이는 (대략적으로) 다음과 같은 교차 출처 요청을 하려고 할 때 발생합니다.
enctype
또는 기타 요청 헤더에서 사용할 수 없는 콘텐츠 유형 설정).프리플라이트가 필요한 작업을 올바르게 수행하고 있는 경우
이 경우 이 답변의 나머지 부분은 여전히 적용됩니다. 하지만 서버가 실행 전 요청을 수신할 수 있는지도 확인해야 합니다(특정 HTTP 메서드나 헤더를 허용하려면
).OPTIONS
(and notGET
,POST
, or whatever you were trying to send) and respond to it with the rightAccess-Control-Allow-Origin
header but alsoAccess-Control-Allow-Methods
andAccess-Control-Allow-Headers
가 됩니다.실수로 프리플라이트를 트리거한 경우
Ajax 요청을 구성하려고 할 때 사람들이 실수를 하는 경우가 있으며, 이로 인해 프리플라이트가 필요한 경우도 있습니다. API가 원본 간 요청을 허용하도록 설계되었지만 사전 실행이 필요한 항목이 필요하지 않은 경우 액세스가 중단될 수 있습니다.
이를 유발하는 일반적인 실수는 다음과 같습니다.
Access-Control-Allow-Origin
및 기타 CORS 응답 헤더를 넣으려고 합니다. 이는 요청에 속하지 않으며 도움이 되는 작업을 수행하지 않으며(자신에게 권한을 부여할 수 있는 권한 시스템의 요점은 무엇입니까?) 응답에만 나타나야 합니다.Content-Type: application/json
header on a GET request that has no request body the content of which to describe (typically when the author confusesContent-Type
andAccept
)를 넣으려고 합니다.이러한 경우 추가 요청 헤더를 제거하면 실행 전 요청이 필요하지 않게 되기에 충분합니다(이렇게 하면 실행 전 요청이 아닌 간단한 요청을 지원하는 API와 통신할 때 문제가 해결됩니다).
불투명한 응답(
no-cors
모드)때로는 HTTP 요청을 해야 하지만 응답을 읽을 필요는 없습니다. 예를 들어 녹화를 위해 서버에 로그 메시지를 게시하는 경우
the
fetch
API (rather thanXMLHttpRequest
)을 사용하는 경우 CORS를 사용하지 않도록 구성할 수 있습니다.참고: CORS에서 수행해야 하는 작업은 수행할 수 없습니다. 답변을 읽을 수 없습니다. 비행 전이 필요한 요청은 할 수 없습니다.
간단한 요청을 할 수 있고 응답을 볼 수 없으며 개발자 콘솔에 오류 메시지가 채워지지 않습니다.
이를 수행하는 방법은
fetch
를 사용하여 요청하고 CORS로 응답을 볼 수 있는 권한을 얻지 못한 경우 표시되는 Chrome 오류 메시지에 설명되어 있습니다.따라서:
으아악CORS의 대안
JSONP
Bob은 CORS가 등장하기 전에 사람들이 교차 출처 Ajax를 수행했던 방식인 JSONP와 같은 해킹을 사용하여 데이터를 제공할 수도 있습니다.
Mallory의 페이지에 데이터를 주입하는 JavaScript 프로그램 형식으로 데이터를 표시하는 방식으로 작동합니다.
Mallory는 Bob이 악성 코드를 제공하지 않도록 신뢰해야 합니다.
공통 주제에 유의하세요. 데이터를 제공하는 사이트는 브라우저에 보내는 데이터에 제3자 사이트가 액세스해도 괜찮다는 것을 브라우저에 알려야 합니다.
JSONP는
<script>
요소를 추가하여 페이지에 이미 있는 함수를 호출하는 JavaScript 프로그램 형식으로 데이터를 로드하므로 JSON을 반환하는 URL에서 JSONP 기술을 사용하려고 시도하면 실패합니다. 일반적으로 CORB 오류가 발생합니다. JSON은 JavaScript가 아니기 때문이죠.두 리소스를 단일 Origin으로 이동
JS가 실행되는 HTML 문서와 요청되는 URL이 동일한 출처(동일한 구성표, 호스트 이름 및 포트 공유)에 있는 경우 동일 출처 정책은 기본적으로 권한을 부여합니다. CORS는 필요하지 않습니다.
프록시
Mallory는 서버 측 코드를 사용하여 데이터를 가져올 수 있습니다(그런 다음 평소와 같이 HTTP를 통해 서버에서 Alice의 브라우저로 데이터를 전달할 수 있습니다).
다음 중 하나가 수행됩니다.CORS 헤더 추가-
응답을 JSONP로 변환-
HTML 문서와 동일한 출처에 존재-
해당 서버 측 코드는 제3자(예: CORS Anywhere)에 의해 작성 및 호스팅될 수 있습니다. 이것이 개인정보 보호에 미치는 영향에 유의하십시오. 제3자는 서버 전체에서 누가 무엇을 프록시하는지 모니터링할 수 있습니다.public 데이터를 읽는 데에만 이 기술을 사용할 수 있습니다.
그러나 다른 사람의 웹사이트에서 콘텐츠를 가져와 직접 표시하는 것은저작권을 위반하는 것이며 법적 조치를 받을 수 있다는 점에 유의하세요.
웹 앱이 아닌 다른 것을 작성개발에는 유용할 수 있지만 프로덕션 사이트에는 실용적이지 않습니다. 사이트의 모든 사용자에게 브라우저의 보안 기능을 비활성화하는 브라우저 확장 프로그램을 설치하도록 요청하는 것은 비합리적입니다.
또한 간단한 요청에만 작동하는 경향이 있습니다(비행 전 OPTIONS 요청을 처리할 때 실패함).
로컬 개발 서버로 적절한 개발 환경 확보 일반적으로 더 나은 접근 방식입니다.
기타 보안 위험
SOP/CORS는 독립적으로 처리해야 하는 XSS, CSRF 또는 SQL 주입 공격을 완화하지 않습니다.
요약