JavaScript 코드에서 Postman에 "요청 된 자원에 'Access-Control-Allow-Origin'헤더가 없습니다"오류가 표시되지 않는 이유는 무엇입니까?


2500

Mod note :이 질문은 Postman이 XMLHttpRequest와 같은 방식으로 CORS 제한을받지 않는 이유에 관한 것입니다. 이 질문은 "No 'Access-Control-Allow-Origin'..."오류를 수정하는 방법 이 아닙니다 .

게시를 중지하십시오 :


RESTful API 내장 Flask 에 연결 하여 JavaScript 를 사용하여 권한 부여를 시도하고 있습니다. 그러나 요청하면 다음 오류가 발생합니다.

XMLHttpRequest가 http : // myApiUrl / login을 로드 할 수 없습니다 . 요청 된 리소스에 'Access-Control-Allow-Origin'헤더가 없습니다. 따라서 원점 '널'은 액세스가 허용되지 않습니다.

API 또는 원격 리소스가 헤더를 설정해야한다는 것을 알고 있지만 Chrome 확장 프로그램 Postman을 통해 요청했을 때 왜 작동 했 습니까?

이것은 요청 코드입니다.

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });

32
localhost에서 요청하거나 HTML을 직접 실행하고 있습니까?
MD. Sahib Bin Mahboob

@ MD.SahibBinMahboob 귀하의 질문을 이해하면 localhost에게 요청합니다-컴퓨터에 페이지가 있고 실행하십시오. 호스팅에 사이트를 배포하면 동일한 결과가 나타납니다.
Mr Jedi


8
자세한 읽기를 찾고 누군가를 위해, MDN 좋은의 모든 아약스와 크로스 원산지 요청에 대한 기사가 developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
샘 이튼

1
노드 js에서 이러한 유형의 오류에 대한 중요한 참고 사항입니다. 경로 설정을 시작하기 전에 server.js 파일을 시작할 때 액세스 헤더를 설정해야합니다. 그렇지 않으면 모든 것이 잘 작동하지만 앱에서 요청하면이 오류가 발생합니다.
Alex J

답변:


1345

내가 올바르게 이해하면 귀하의 페이지가 아닌 다른 도메인에 XMLHttpRequest 를하고 있습니다. 따라서 브라우저는 일반적으로 보안상의 이유로 동일한 출처에서 요청을 허용하므로 브라우저를 차단합니다. 도메인 간 요청을 수행하려는 경우 다른 작업을 수행해야합니다. 이를 달성하는 방법에 대한 튜토리얼은 Using CORS 입니다.

우편 배달부를 사용하는 경우이 정책에 의해 제한되지 않습니다. Cross-Origin XMLHttpRequest 에서 인용 :

일반 웹 페이지는 XMLHttpRequest 객체를 사용하여 원격 서버와 데이터를주고받을 수 있지만 동일한 원본 정책에 의해 제한됩니다. 확장은 그렇게 제한되지 않습니다. 교차 출처 권한을 먼저 요청하는 한 확장은 원래 외부의 원격 서버와 통신 할 수 있습니다.


7
네가 옳아. 내 페이지와 다른 도메인에 요청하고 있습니다. API가 서버에 있고 localhost에서 요청을 실행합니다. 답변을 수락하기 전에 "요청을 직접 실행"이 무슨 뜻인지 설명해 주실 수 있습니까? POSTMAN은 도메인을 사용하지 않습니까?
Mr Jedi

181
브라우저가 요청을 차단하지 않습니다. 교차 출처 아약스 요청을 완전히 차단하는 브라우저는 IE7 이상입니다. IE7 및 이전 버전을 제외한 모든 브라우저는 CORS 사양 (IE8 및 IE9를 부분적으로)을 구현합니다. 요청을 기반으로 적절한 헤더를 반환하여 API 서버에서 CORS 요청을 옵트 인하면됩니다. mzl.la/VOFrSz 에서 CORS 개념을 읽어야 합니다. Postman은 XHR을 통해서도 요청을 보냅니다. 우편 배달부를 사용할 때 동일한 문제가 표시되지 않으면 우편 배달부를 통해 무의식적으로 동일한 요청을 보내지 않는 것입니다.
레이 니콜러스

10
@ MD.SahibBinMahboob Postman이 "자바 / 파이썬"코드로 요청을 보내지 않습니다. 브라우저에서 직접 요청을 보내고 있습니다. Chrome 확장 프로그램의 XHR은 특히 교차 출처 요청이 포함 된 경우 약간 다르게 작동합니다 .
레이 니콜러스

249

경고 :를 사용하면 Access-Control-Allow-Origin: *API / 웹 사이트가 CSRF ( Cross-Site Request Forgery) 공격에 취약해질 수 있습니다. 이 코드를 사용하기 전에 위험이해 했는지 확인하십시오 .

PHP를 사용하는 경우 해결하는 것이 매우 간단합니다 . 요청을 처리하는 PHP 페이지의 시작 부분에 다음 스크립트를 추가하십시오.

<?php header('Access-Control-Allow-Origin: *'); ?>

Node-red 를 사용 하는 경우 다음 행을 주석 해제 하여 파일 에서 CORS 를 허용해야합니다 node-red/settings.js.

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
 origin: "*",
 methods: "GET,PUT,POST,DELETE"
},

Flask 를 사용 하는 경우 질문과 동일합니다. 먼저 설치해야합니다flask-cors

$ pip install -U flask-cors

그런 다음 응용 프로그램에 Flask cors를 포함하십시오.

from flask_cors import CORS

간단한 응용 프로그램은 다음과 같습니다.

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

자세한 내용은 Flask 설명서를 확인할 수 있습니다 .


93
그것은 안전하지 않은 것
llazzaro

153
CORS의 기능을 모르기 때문에 CORS 를 끄면 안됩니다 . 이것은 끔찍한 대답입니다.
meagar

124
안전하지는 않지만 보안에 관한 문제가 아니라 작업을 수행하는 방법에 대한 문제였습니다. 이는 도메인 간 AJAX 요청을 처리 할 때 개발자가 선택해야하는 옵션 중 하나입니다. 문제를 해결하는 데 도움이되었으며 응용 프로그램의 경우 데이터의 출처를 신경 쓰지 않습니다. 대상 도메인에서 PHP로 모든 입력을 삭제하므로 누군가가 정크를 게시하려는 경우 시도하십시오. 여기서 요점은 대상 도메인에서 도메인 간 AJAX를 허용 할 수 있다는 것입니다. 답변 +1
ZurabWeb

23
Piero가 전하는 일반적인 메시지에 동의하지만 보안에 관한 것이 아니라 보안이 중요합니다. 나는 이것이 적어도 "이것은 일반적으로 나쁘다! 당신이하고있는 일을 알지 못한다면 이것을하지 마십시오! 여기에 더 많은 문서가 있습니다 : ..."와 같은 말을해야한다고 생각합니다. 나는 누군가가 여기 와서 싫어하는 것을 싫어하고 "아,이 헤더를 추가 / 조정할 수 있고 좋다"고 생각합니다. 전체 파급 효과를 모릅니다. 내 말은, 그들 모두가 연구하는 것이지만 여전히 그래요.
Thomas F.

4
이 답변이 마음에 듭니다 ... 같은 문제가 있고 해결합니다 ... 보안 문제가 있다고 설명했지만 다른 문제이며 모든 사람이 문제를 생각하고 해결할 수 있도록하겠습니다.
Ari Waisberg

63

때문에
$ 아약스 ({유형 : "POST"는 - 통화 옵션
$이 (.post 호출 - POST를

둘 다 다릅니다. 우편 배달부에서는 "POST"를 올바르게 호출하지만 전화를 걸면 "OPTIONS"가됩니다.

C # 웹 서비스의 경우- 웹 API

<system.webServer> 태그 아래 web.config 파일에 다음 코드를 추가하십시오 . 이것은 작동합니다 :

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

Ajax 호출에서 실수하지 않도록하십시오

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);
    },
    error: function () {
        console.log("error");
    }
});

참고 : 당신이 콘텐츠를 다운로드를 찾고 있다면 타사 웹 사이트에서 다음 이 도움이되지 않습니다 . 다음 코드는 시도 할 수 있지만 JavaScript는 시도 할 수 없습니다.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");

이 구성은 Azure Services의 Wordpress에서 동일한 오류를 해결했습니다. 감사.
Andre Mesquita

9
외부 도메인의 요청을 피하기 위해 특정 출처 값을 사용하는 것이 좋습니다. 그래서 예를 대신에 *사용https://www.myotherdomain.com
pechar


8

CORS 제한 적용은 서버에 의해 정의되고 브라우저에 의해 구현되는 보안 기능 입니다.

브라우저는 서버의 CORS 정책을보고 존중합니다.

그러나 Postman 도구는 서버의 CORS 정책을 신경 쓰지 않습니다.

이것이 CORS 오류가 브라우저에 나타나지만 Postman에는 나타나지 않는 이유입니다.


1
그렇습니다. 왜이 작은 세부 사항에주의를 기울여야하는지 충분히 강조 할 수 없습니다. 보안에 관해 이야기 할 때 CORS가이를 구현 하는 클라이언트 만큼 강력하다고 언급하는 것이 가장 중요 합니다. 간단한 HttpClient (서버 측 코드)를 가져 와서 요청을 수행하는 프록시를 구축한다고 상상해보십시오. 보안을 완전히 우회하여 CORS 표준을 열악한 솔루션으로 남길 수 있습니다.
Christopher Bonitz

7

아래의 API로 조사 할 때 귀하의 질문 에 http : // myApiUrl / login 대신 http://example.com을 사용 합니다.

귀하의 페이지가 http : //my-site.local : 8088 에 있다고 가정합니다 .

다른 결과를 보는 이유는 다음과 같습니다.

  • 헤더 설정 Host=example.com(API)
  • 헤더를 설정하지 않았습니다 Origin

이것은 사이트와 API가 동일한 도메인을 가질 때 브라우저가 요청을 보내는 방법과 유사합니다 (브라우저도 헤더 항목을 설정 Referer=http://my-site.local:8088하지만 Postman에서는 보이지 않습니다). Origin헤더가되어 있지 설정, 일반적으로 서버는 기본적으로 이러한 요청을 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

이것은 Postman이 요청을 보내는 표준 방법입니다. 그러나 사이트와 API의 도메인이 다른 경우 브라우저가 요청을 다르게 보낸 다음 CORS 가 발생하고 브라우저가 자동으로 다음을 수행합니다.

  • 헤더를 설정합니다 Host=example.com(귀하의 API로)
  • 헤더를 설정합니다 Origin=http://my-site.local:8088(귀하의 사이트)

(헤더 Referer의 값 은와 동일합니다 Origin). 이제 Chrome의 콘솔 및 네트워크 탭에 다음이 표시됩니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

당신이있을 때 Host != Origin그것을 일반적으로이 CORS이며, 서버는 이러한 요청을 감지 할 때 기본적으로 블록을 .

Origin=null로컬 디렉토리에서 HTML 컨텐츠를 열 때 설정되며 요청을 보냅니다. 같은 상황은 <iframe>아래 스 니펫과 같이 내부에 요청을 보낼 때입니다 (그러나 여기에는 Host헤더가 전혀 설정되어 있지 않습니다). 일반적으로 HTML 사양이 불투명 원점을 말하는 모든 곳에서로 변환 할 수 있습니다 Origin=null. 이에 대한 자세한 내용은 여기를 참조하십시오 .

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

간단한 CORS 요청을 사용하지 않는 경우 일반적으로 브라우저는 기본 요청을 보내기 전에 OPTIONS 요청을 자동으로 보냅니다 . 자세한 정보는 여기에 있습니다 . 아래 스 니펫은 다음과 같습니다.

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

CORS 요청을 허용하도록 서버 구성을 변경할 수 있습니다.

다음은 nginx (nginx.conf 파일) 에서 CORS를 설정하는 구성 예 always/"$http_origin"입니다. nginx 및 "*"Apache 설정 에 매우주의 하십시오. 그러면 모든 도메인에서 CORS가 차단 해제됩니다.

다음은 Apache (.htaccess 파일) 에서 CORS를 설정하는 구성 예입니다.


2

다른 사용 사례에서 동일한 오류가 발생했습니다.

유스 케이스 : 크롬에서 Spring REST 엔드 포인트를 각도 로 호출하려고 할 때 크롬 에서.

여기에 이미지 설명을 입력하십시오

해결 방법 : 각 컨트롤러 클래스 위에 @CrossOrigin ( "*") 주석을 추가하십시오 .

여기에 이미지 설명을 입력하십시오


보안 대신 * 대신 localhost를 사용합니다.
neo7bf

-1

.NET을 중간 계층으로 사용하는 경우 경로 속성을 명확하게 확인하십시오 (예 :

이럴 때 문제가 있었어요

[Route("something/{somethingLong: long}")] //Space.

이것으로 고쳤습니다.

[Route("something/{somethingLong:long}")] //No space

-1

.NET Core Web API 프로젝트에만 다음 변경 사항을 추가하십시오.

  1. Startup.cs 파일 services.AddMvc()ConfigureServices()메소드 에서 행 뒤에 다음 코드를 추가 하십시오.
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. Startup.cs 파일 app.UseMvc()Configure()메소드 에서 다음 코드를 행 뒤에 추가 하십시오.
app.UseCors(options => options.AllowAnyOrigin());
  1. 도메인 외부에서 액세스하려는 컨트롤러를 열고 컨트롤러 레벨에서 다음 속성을 추가하십시오.
[EnableCors("AllowOrigin")]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.