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

XmlHttpRequest error: Origin null is not allowed by Access-Control-Allow-Origin

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

Flickr端工作正常,但当我尝试从Panoramio中删除cx1(0)时,我在Chrome的控制台中看到一个错误:

XMLHttpRequest cannot load 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. Origin null is not allowed by Access-Control-Allow-Origin.

如果我直接从浏览器查询该URL,它就可以正常工作。发生了什么事,我能避开吗?我是在错误地编写查询,还是Panoramio这样做妨碍了我的工作?

谷歌没有在错误信息中找到任何有用的匹配项。

编辑

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

1
2
3
4
5
6
7
8
9
10
11
$().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

多亏了达林的帮助。上面的代码是错误的。改为使用:

1
2
3
4
5
6
7
$().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...
  });
});


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

  • 您没有将"jsonp"类型说明符传递给您的$.get,因此它使用了一个普通的xmlhttpRequest。但是,您的浏览器支持CORS(跨源站资源共享),允许跨域XMLHttpRequest(如果服务器终止)。这就是Access-Control-Allow-Origin的头条出现的地方。

  • 我相信你提到过你是从一个文件中运行它的。CORS报头有两种方法来表示跨域XHR正常。一个是发送Access-Control-Allow-Origin: *(如果您通过$.get到达flickr,他们一定是这么做的),另一个是回送Origin头的内容。但是,file://URL生成的Origin为空,不能通过echo back进行授权。

  • 第一个问题是通过达林建议使用$.getJSON迂回解决的。如果在URL中看到子字符串callback=?,那么将请求类型从默认的"json"更改为"jsonp"就有点神奇了。

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

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

  • 如果您尝试使用jsonp,请确保以下情况之一:
    • 你用的是$.get,把dataType设为jsonp
    • 您使用的是$.getJSON,并在URL中包含callback=?
  • 如果您试图通过CORS执行跨域XMLHttpRequest…
  • 确保您正在通过http://进行测试。通过file://运行的脚本对CORS的支持有限。
  • 确保浏览器实际上支持CORS。(Opera和Internet Explorer来晚了)

  • 您可能需要在调用的脚本中添加一个头部,下面是我在PHP中要做的:

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

    有关跨域Ajax OU服务Web(法语)的更多详细信息。


    对于简单的HTML项目:

    1
    2
    cd project
    python -m SimpleHTTPServer 8000

    然后浏览您的文件。


    在Google Chrome v5.0.375.127上为我工作(我收到警报):

    1
    2
    3
    4
    $.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(至少在我的机器上):

    1
    2
    3
    4
    $.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=?,以便您可以使用匿名函数。您可以在文档中了解更多关于它的信息。

    另一句话是你不应该叫埃瓦尔。传递给匿名函数的参数将被jquery解析为json。


    只要请求的服务器支持JSON数据格式,就使用JSONP(JSON填充)接口。它允许您在没有代理服务器或花哨的头文件的情况下进行外部域请求。


    它是相同的源策略,您必须使用JSON-P接口或在同一主机上运行的代理。


    如果您正在进行本地测试或从类似于file://的地方调用文件,那么您需要禁用浏览器安全性。

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


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

    1
    2
    3
    4
    5
    6
    <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。


    在我的例子中,相同的代码在Firefox上运行得很好,但在Google Chrome上却不行。谷歌Chrome的javascript控制台说:

    1
    2
    3
    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正确匹配,然后它工作得很好。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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;
        });
    }

    最后要注意的是,Mozilla文档明确指出

    The above example would fail if the header was wildcarded as:
    Access-Control-Allow-Origin: *. Since the Access-Control-Allow-Origin explicitly mentions http://foo.example,
    the credential-cognizant content is returned to the invoking web
    content.

    因此,使用"*"不仅仅是一个坏习惯。根本不起作用。)


    我使用Apache服务器,所以我使用了mod_代理模块。启用模块:

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

    然后添加:

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

    最后,将代理URL传递到脚本。


    乡亲们,

    我也遇到了类似的问题。但使用小提琴,我能够解决这个问题。问题是,在Web API端的CORS实现中配置的客户机URL不能有一个尾随的正斜杠。通过Google Chrome提交请求并检查fiddler headers部分的textview选项卡后,错误消息的状态如下:

    *"指定的策略来源u客户端u url://"无效。它不能以正斜杠结尾。"

    这真的很奇怪,因为它在Internet Explorer上没有任何问题,但在使用Google Chrome进行测试时让我头疼。

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

    谢谢,安迪


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

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

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

    然后在以东十一〔二十二〕号服役。


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

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

    确保您使用的是最新版本的jquery。我们在jquery 1.10.2中遇到此错误,使用jquery 1.11.1后解决了此错误。