XmlHttpRequest错误:Access-Control-Allow-Origin不允许使用Origin null


550

我正在开发一个页面,该页面通过jQuery的AJAX支持从Flickr和Panoramio中提取图像。

Flickr方面运行良好,但是当我尝试$.get(url, callback)从Panoramio进行操作时,我在Chrome的控制台中看到错误:

XMLHttpRequest无法加载http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150。Access-Control-Allow-Origin不允许使用Origin null。

如果我直接从浏览器查询该URL,它将正常工作。这是怎么回事,我可以解决这个问题吗?我是在错误地编写查询,还是Panoramio这样做妨碍了我的工作?

Google并未在错误消息中显示任何有用的匹配项。

编辑

这是一些显示问题的示例代码:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';

  $.get(url, function (jsonp) {
    var processImages = function (data) {
      alert('ok');
    };

    eval(jsonp);
  });
});

您可以在线运行示例

编辑2

感谢达林在这方面的帮助。 上面的代码错误。 使用此代替:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';

  $.get(url, function (data) {
    // can use 'data' in here...
  });
});

1
从中发出请求的URL是什么样的?这不刚好是动态生成的iframe,你document.write进入,例如?
佩卡

5
您能否将HTTP响应从请求发布到每个服务。我敢打赌Panoramio没有提供Access-Control-Allow-Origin。有关示例,请参见w3.org/TR/cors
凯文·哈坎森

2
@Kevin,如果服务器发送JSONP,则不需要这些标头。
达林·迪米特洛夫

@Pekka,目前我正在本地计算机上运行该页面(file:///C:/)。不iframe涉及。
德鲁·诺克斯

1
@drew如果从http URL运行会发生什么?它不应该这样改变,而只是排除可能性。
佩卡

Answers:


423

据我所知,您有两个问题:

  1. 您没有将“ jsonp”类型说明符传递给您的 $.get,因此它使用的是普通的XMLHttpRequest。但是,您的浏览器支持CORS(跨域资源共享),如果服务器确定,则允许跨域XMLHttpRequest。那是Access-Control-Allow-Origin头文件进入的地方。

  2. 我相信您提到您是通过file:// URL运行它的。CORS标头有两种方式来表示跨域XHR正常。一是送Access-Control-Allow-Origin: *(如果您通过到达Flickr $.get,他们一定在发送),另一种是回显Origin标头的内容。然而,file:// URL产生的null Origin不能通过回显进行授权。

达林的使用建议以一种about回的方式解决了第一个问题$.getJSON。如果看到callback=?URL中的子字符串,将请求类型从其默认值“ json”更改为“ jsonp”确实有点魔术。

这样就解决了第二个问题,不再尝试从file://URL 执行CORS请求。

为了向其他人说明,以下是简单的故障排除说明:

  1. 如果您尝试使用JSONP,请确保符合以下条件之一:
    • 您正在使用$.get并设置dataTypejsonp
    • 您正在使用$.getJSON并包含callback=?在URL中。
  2. 如果您尝试通过CORS进行跨域XMLHttpRequest ...
    1. 确保您正在通过进行测试 http://。通过运行的脚本file://对CORS的支持有限。
    2. 确保浏览器实际上支持CORS。(Opera和Internet Explorer迟到了)

45
那么解决方案是什么?
jQuerybeast 2011年

19
回调=?FTW
Tim

10
如果使用参数--allow-file-access-from-files
echox 2012年

1
callback=?不适用于我,但有效jsonp=?。有什么解释吗?
足癣2012年

1
我是否必须安装网络服务器以进行测试http://?还是有一种方法可以简单地使用该协议打开文件?
Will Sewell 2014年

76

您可能需要在调用的脚本中添加HEADER,这是我在PHP中要做的事情:

header('Access-Control-Allow-Origin: *');

跨域AJAX ou服务WEB(法语)中的更多详细信息。


1
@Uri:取决于您的HTTP服务器。使用Apache,您将需要研究mod_headers。
ssokolow 2011年

4
@Uri <meta http-equiv =“ Access-Control-Allow-Origin” content =“ *”>
Herberth Amaral 2012年

7
@HerberthAmaral我尝试将其添加到<head> </ head>内,但这对我不起作用。我在iOS Safari和Chrome中尝试使用它,但是在控制台中,Access-Control-Allow-Origin错误不允许出现原点为null的错误。
thandasoru '04年

3
出于安全原因,它无法在html文件的开头运行。它必须是标题。stackoverflow.com/questions/7015782/...
贾斯汀空白

它不能在HTML中。它必须由通过网络将HTML页面发送到浏览器的程序(所谓的Web服务器)指定。
RomanPlášil17年

70

对于一个简单的HTML项目:

cd project
python -m SimpleHTTPServer 8000

然后浏览您的文件。


1
而真棒和作品,当你去0.0.0.0:8000,并尝试POST请求你:code 501, message Unsupported method ('POST')在谷歌。
pjammer

“当一个Python Web服务器(例如,cherrypy)表示正在0.0.0.0上运行时,这意味着它正在侦听最终到达该计算机的所有TCP通信,无论请求的主机名或IP如何。” 因此,也许尝试发布到本地主机:8000 stackoverflow.com/a/4341808/102022
eric.christensen 2014年

20

在Google Chrome v5.0.375.127上对我有效(我收到警报):

$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
    alert(json.photos[1].photoUrl);
});

我也建议您改用该$.getJSON()方法,因为以前的方法在IE8上不起作用(至少在我的机器上):

$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150', 
function(json) {
    alert(json.photos[1].photoUrl);
});

您可以从这里在线尝试。


更新:

现在,您已经显示了代码,我可以看到它的问题。您同时具有匿名函数和内联函数,但是两者都会被调用processImages。这就是jQuery的JSONP支持的工作方式。请注意,我是如何定义的,callback=?以便您可以使用匿名函数。您可以在文档中阅读有关它的更多信息

另一点是您不应调用eval。传递给匿名函数的参数已由jQuery解析为JSON。


好的,让我再试一次。我使用的是Chrome btw“ 6.0.472.51 beta”的其他版本。
德鲁·诺阿克斯

您的代码对我有用。我用一些可以解决问题的代码更新了我的问题。
Drew Noakes

感谢您的提示getJSON ...我派生了您的jsFiddle示例来显示问题(jsfiddle.net/ZfvKm),现在看到错误消息XMLHttpRequest无法加载panoramio.com/wapi/data/…。Access-Control-Allow-Origin不允许使用Origin fiddle.jshell.net
德鲁·诺阿克斯

@Darin,感谢您的更新。我明白了您的意思,并且已经对此进行了一些组合,但是我还没有找到访问返回对象的方法。您可以更新jsFiddle示例以显示对数据的访问吗?如果将回调设置为,?则返回的JSON会用括号括起来。您没有为回调函数定义参数,并且值this似乎没有响应对象(至少.datanull)。
德鲁·诺阿克斯

@Darin,太棒了。非常感谢。现在运作良好。对于任何其他阅读本文的人,包含的内容callback=?告诉jQuery内部生成一个随机函数名称,从而导致对您传递给的匿名函数的调用.getJSON。感激。
Drew Noakes 2010年

8

只要请求的服务器支持JSON数据格式,请使用JSONP(JSON填充)接口。它使您可以发出外部域请求,而无需代理服务器或精美的标题。



4

我们通过http.conf文件进行管理(已编辑,然后重新启动HTTP服务):

<Directory "/home/the directory_where_your_serverside_pages_is">
    Header set Access-Control-Allow-Origin "*"
    AllowOverride all
    Order allow,deny
    Allow from all
</Directory>

在中Header set Access-Control-Allow-Origin "*",您可以放置​​一个精确的URL。


1
这不适用于XAMPP的Apache。问题仍然存在。
猛禽

1
这是不安全的。看这里为什么;stackoverflow.com/questions/7564832/…–
Rob

如@RobQuist所说,这是不安全的。
d337

4

如果您正在进行本地测试或通过类似的方式调用文件 file://则需要禁用浏览器安全性。

在MAC上: open -a Google\ Chrome --args --disable-web-security


3

就我而言,相同的代码在Firefox上可以正常工作,但在Google Chrome上却不能。谷歌浏览器的JavaScript控制台说:

XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234. 
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"

我必须删除Ajax URL的www部分,以使其与原始URL正确匹配,然后工作正常。


2

并非所有服务器都支持jsonp。它要求服务器在其结果中设置回调函数。我用它来从返回纯json但不支持jsonp的站点获取json响应:

function AjaxFeed(){

    return $.ajax({
        url:            'http://somesite.com/somejsonfile.php',
        data:           {something: true},
        dataType:       'jsonp',

        /* Very important */
        contentType:    'application/json',
    });
}

function GetData() {
    AjaxFeed()

    /* Everything worked okay. Hooray */
    .done(function(data){
        return data;
    })

    /* Okay jQuery is stupid manually fix things */
    .fail(function(jqXHR) {

        /* Build HTML and update */
        var data = jQuery.parseJSON(jqXHR.responseText);

        return data;
    });
}

1

我使用Apache服务器,所以我使用过mod_proxy模块。启用模块:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

然后加:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

最后,将proxy-url传递给脚本。


1

最后,Mozilla文档明确指出

如果标头通配符为:Access-Control-Allow-Origin:*,则上面的示例将失败 由于Access-Control-Allow-Origin明确提及http://foo.example,因此凭据识别内容将返回到调用的Web内容。

因此,使用'*'不只是一个不好的做法。根本行不通:)


1

对于PHP-在Chrome,Safari和Firefox中为我工作

https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null

header('Access-Control-Allow-Origin: null');

使用axios将php实时服务与file://一起使用


这对我也有效,请注意STRING的null是多少,而不是实际的NULL。我使用它是header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);因为它也允许从远程服务器到另一个服务器的跨源访问,而对于本地文件则降至(字符串)null。
Louis Loudog Trottier

0

我在Chrome中也遇到了相同的错误(我没有测试其他浏览器)。这是由于我浏览的是domain.com而不是www.domain.com。有点奇怪,但是我可以通过在.htaccess中添加以下几行来解决问题。它将domain.com重定向到www.domain.com并解决了问题。我是一个懒惰的Web访问者,所以我几乎从不键入www,但在某些情况下显然是必需的。

RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]


0

民间,

我遇到了类似的问题。但是使用Fiddler,我可以解决这个问题。问题在于,在Web API端的CORS实现中配置的客户端URL不得带有尾随正斜杠。通过Google Chrome提交请求并检查标题TextView标签后 Fiddler部分,错误消息显示如下内容:

*“指定的策略来源your_client_url:/'无效。 它不能以正斜杠结尾。”

这确实很古怪,因为它在Internet Explorer上可以正常工作,但是在使用Google Chrome浏览器进行测试时让我头疼。

我在CORS代码中删除了正斜杠并重新编译了Web API,现在可以通过Chrome和Internet Explorer访问该API,而不会出现任何问题。请试一下。

谢谢,安迪


0

上面CodeGroover发布的解决方案中有一个小问题,如果您更改文件,则必须重新启动服务器才能实际使用更新的文件(至少在我的情况下)。

所以搜索了一下,我发现这个要使用:

sudo npm -g install simple-http-server # to install
nserver # to use

然后它将在投放http://localhost:8000


1
尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。- 来自评论
Vi100

澄清了链接。
MiJyn
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.