当我的JavaScript代码出现时,为什么Postman不会出现“在请求的资源上没有'Access-Control-Allow-Origin'标头”错误?


2500

注释:这个问题是关于为什么Postman不受XMLHttpRequest一样的CORS限制。此问题不是关于如何解决“无'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
您是从本地主机发出请求还是直接执行HTML?
MD。Sahib Bin Mahboob 2013年

@ MD.SahibBinMahboob如果我理解您的问题,我会向localhost请求-我的计算机上有一个页面,可以运行它。当我在托管站点上部署站点时,结果相同。
杰迪先生


8
对于希望阅读更多内容的人员,MDN上有一篇很好的文章,内容涉及ajax和跨源请求:developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Sam Eaton 2015年

1
节点js中此类错误的重要说明。在开始设置路由之前,必须在server.js文件的启动中设置访问标头。否则,一切都会很好地运行,但是当您从应用程序发出请求时,会出现此错误。
Alex J

Answers:


1343

如果我理解正确,那么您正在向页面所在的其他域执行XMLHttpRequest。因此,由于安全原因,浏览器通常会阻止来自同一来源的请求,因此阻止了它。当您想进行跨域请求时,需要做一些不同的事情。有关如何实现此目标的教程是使用CORS

使用邮递员时,它们不受此政策的限制。引用自跨域XMLHttpRequest

常规网页可以使用XMLHttpRequest对象从远程服务器发送和接收数据,但是它们受同一原始策略的限制。扩展不受限制。扩展可以在其起源之外与远程服务器通信,只要它首先请求跨域许可。


7
你是对的。我正在向与页面不同的域请求。API在服务器上,我运行来自本地主机的请求。在我接受答案之前,您能解释一下“直接执行请求”是什么意思吗?邮递员不使用域名吗?
杰迪先生

180
浏览器未阻止该请求。唯一可以完全阻止跨域ajax请求的浏览器是IE7或更早版本。除IE7和更早版本外,所有浏览器均实现CORS规范(部分为IE8和IE9)。您需要做的就是通过基于请求返回正确的标头来选择加入API服务器上的CORS请求。您应该在mzl.la/VOFrSz中阅读CORS概念。邮递员也通过XHR发送请求。如果在使用邮递员时没有遇到相同的问题,这意味着您在不知不觉中不通过邮递员发送相同的请求。
Ray Nicholus

10
@ MD.SahibBinMahboob邮递员未发送“来自您的Java / python”代码的请求。它是直接从浏览器发送请求。 Chrome扩展程序中的XHR的工作原理有所不同,尤其是涉及跨域请求时
Ray Nicholus

249

警告:使用Access-Control-Allow-Origin: *会使您的API /网站容易受到跨站点请求伪造(CSRF)攻击。在使用此代码之前,请确保您了解风险

如果您使用的是PHP,则非常简单。只需在处理请求的PHP页面的开头添加以下脚本:

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

如果您正在使用节点红色的,你必须让CORSnode-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

然后在您的应用程序中包括Flas 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 2014年

153
您不应该关闭 CORS,因为您不知道它的用途。这是一个可怕的答案。
meagar

124
尽管可能并不安全,但问题不在于安全性,而在于如何完成任务。这是开发人员在处理跨域AJAX请求时必须选择的选项之一。它帮助我解决了这个问题,对于我的应用程序,我不在乎数据来自何处。我用目标域上的PHP清理了所有输入,因此,如果有人想向其中发布一些垃圾,请让他们尝试。这里的要点是,可以从目标域允许跨域AJAX。+1为答案。
ZurabWeb

23
尽管我同意Piero给出的一般信息,但并不是专门针对安全性,而是安全性是一个问题。我认为这至少应该说出类似“这通常很糟糕!除非您知道自己在做什么,否则请不要这样做!这里有更多文档:...”,并可能简要解释了原因。我讨厌有人来这里,只是想:“哦,我可以添加/调整此标头,我很好!” 并且不知道全部后果。我的意思是,研究和全部研究都在他们身上,但仍然如此。
Thomas F.

4
我喜欢这个答案...我有同样的问题,并且可以解决...他解释了一些安全问题,但这是另一个问题,让每个人都可以单独思考并解决该问题...
Ari Waisberg

63

因为
$ .ajax({type:“ POST” -调用选项
$ .post( -调用POST

两者是不同的。邮递员正确地称呼“ POST”,但是当我们称呼它为“ OPTIONS”时。

对于C#Web服务-Web 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上的相同错误。谢谢。
安德烈·梅斯基塔

9
我建议使用特定的原始值来避免来自外部域的请求。例如,代替*使用https://www.myotherdomain.com
pechar


8

应用CORS限制是由服务器定义并由浏览器实现的安全功能。

浏览器查看服务器的CORS策略并遵守该策略。

但是,邮递员工具不会打扰服务器的CORS策略。

这就是CORS错误出现在浏览器中而不出现在Postman中的原因。


1
是的,我不能太强调为什么这个小细节值得关注。在谈到安全性时,最重要的是要提到CORS与实现它的客户端一样强大。因此,想象一下您采用了一个简单的HttpClient(服务器端代码)并构建了一个代理,然后由代理来处理您的请求...可以完全规避安全性,而实际上将CORS标准作为一个糟糕的解决方案
Christopher Bonitz,

7

在下面的API调查中,我使用http://example.com而不是您的问题中的http:// myApiUrl / login,因为第一个有效。

我认为您的页面位于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 != OriginCORS时,并且服务器检测到此类请求时,通常默认情况下将阻止

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上打开CORS的示例配置(.htaccess文件)


2

在不同的用例中遇到相同的错误。

用例:在Chrome中,当尝试以角度调用Spring REST端点时。

在此处输入图片说明

解决方案:在相应的Controller类顶部添加@CrossOrigin(“ *”)批注。

在此处输入图片说明


为了安全
起见

-1

如果您使用.NET作为中间层,请清楚检查route属性,例如,

我有这样的问题

[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")]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.