对于从文件:// URL 运行的应用程序发出的请求,“Access-Control-Allow-Origin 不允许 Origin null”错误

Posted

技术标签:

【中文标题】对于从文件:// URL 运行的应用程序发出的请求,“Access-Control-Allow-Origin 不允许 Origin null”错误【英文标题】:“Origin null is not allowed by Access-Control-Allow-Origin” error for request made by application running from a file:// URL 【发布时间】:2013-04-22 02:53:51 【问题描述】:

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

Flickr 端工作正常,但是当我尝试从 Panoramio 发送 $.get(url, callback) 时,我在 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 没有在 error message 上找到任何有用的匹配项。

编辑

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

$().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);
  );
);

你可以run the example online。

编辑 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...
  );
);

【问题讨论】:

您从 发出请求的 URL 是什么样的?例如,这不会是您 document.write 动态生成的 iframe 吗? 您能否将请求中的 HTTP 响应发布到每个服务。我敢打赌 Panoramio 没有提供 Access-Control-Allow-Origin。有关示例,请参阅w3.org/TR/cors。 @Kevin,如果服务器发送 JSONP,则不需要这些标头。 @Pekka,我现在正在本地机器上运行该页面 (file:///C:/)。不涉及iframe @drew 如果您从 http URL 运行它会发生什么?这样做不应该有什么不同,而只是为了排除这种可能性。 【参考方案1】:

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

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

    我相信您提到您是从 file:// URL 运行它的。 CORS 标头有两种方式表明跨域 XHR 正常。一种是发送Access-Control-Allow-Origin: *(如果您是通过$.get 访问Flickr,他们一定是这样做的),另一种是回显Origin 标头的内容。但是,file:// URL 会生成一个空的 Origin,无法通过回显授权。

Darin 建议使用$.getJSON 以迂回的方式解决了第一个问题。如果它在 URL 中看到子字符串 callback=?,将请求类型从默认的“json”更改为“jsonp”,这会有点神奇。

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

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

    如果您尝试使用 JSONP,请确保满足以下条件之一: 您正在使用$.get 并将dataType 设置为jsonp。 您正在使用$.getJSON 并在网址中包含callback=?。 如果您尝试通过 CORS 执行跨域 XMLHttpRequest...
      确保您正在通过http:// 进行测试。通过 file:// 运行的脚本对 CORS 的支持有限。 确保浏览器actually supports CORS。 (Opera 和 Internet Explorer 迟到了)

【讨论】:

那么有什么解决办法呢? 某些浏览器(如 chrome)如果以参数 --allow-file-access-from-files 开头,则允许 CORS callback=? 对我不起作用,但 jsonp=? 对我有用。对此有何解释? @crunkchitis:我不确定为什么callback=? 不适合你,因为当前的 jQuery 文档仍然说它应该,但是,如果我没看错的话,他们也会说anything_else=? 也可以使用。【参考方案2】:

您可能需要在调用的脚本中添加一个 HEADER,这是我在 php 中必须做的:

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

Cross domain AJAX ou services WEB(法语)了解更多详情。

【讨论】:

【参考方案3】:

对于一个简单的 html 项目:

cd project
python -m SimpleHTTPServer 8000

然后浏览您的文件。

【讨论】:

【参考方案4】:

在 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);
);

你可以试试online from here。


更新:

现在你已经展示了你的代码,我可以看到它的问题。您同时拥有匿名函数和内联函数,但两者都将被称为processImages。这就是 jQuery 的 JSONP 支持的工作原理。请注意我是如何定义 callback=? 的,以便您可以使用匿名函数。您可以阅读更多about it in the documentation。

另外一点是你不应该调用 eval。传递给匿名函数的参数已经被 jQuery 解析为 JSON。

【讨论】:

我得到 Uncaught TypeError: $.get is not a function at :1:3【参考方案5】:

只要请求的服务器支持JSON数据格式,就使用JSONP(JSON Padding)接口。它允许您在没有代理服务器或花哨的标头内容的情况下发出外部域请求。

【讨论】:

【参考方案6】:

是same origin policy,您必须使用 JSON-P 接口或在同一主机上运行的代理。

【讨论】:

【参考方案7】:

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

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

【讨论】:

【参考方案8】:

我们通过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 "*",你可以放一个精确的网址。

【讨论】:

这不适用于 XAMPP 的 Apache。问题依然存在。 这是不安全的。看这里为什么; ***.com/questions/7564832/… 正如@RobQuist 所说的那样不安全。【参考方案9】:

就我而言,相同的代码在 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 正确匹配,然后它工作正常。

【讨论】:

【参考方案10】:

并非所有服务器都支持 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;
    );

【讨论】:

【参考方案11】:

我使用 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 传递给您的脚本。

【讨论】:

【参考方案12】:

最后要注意的是Mozilla documentation explicitly says

如果标头被通配符为: Access-Control-Allow-Origin: *. 由于 Access-Control-Allow-Origin 明确提到了http://foo.example, 凭证识别内容返回到调用网络 内容。

因此,使用“*”不仅仅是一种不好的做法。根本行不通:)

【讨论】:

【参考方案13】:

对于 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 live services with file://

【讨论】:

这也适用于我,注意 null 是一个字符串而不是实际的 NULL。我将它用作header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);,它也允许从远程服务器到另一个服务器的交叉源,并且本地文件的 (string) null。【参考方案14】:

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

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

【讨论】:

【参考方案15】:

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

【讨论】:

【参考方案16】:

伙计们,

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

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

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

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

谢谢, 安迪

【讨论】:

【参考方案17】:

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

于是搜索了一下,找到了this one 使用:

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

然后它将服务于http://localhost:8000

【讨论】:

以上是关于对于从文件:// URL 运行的应用程序发出的请求,“Access-Control-Allow-Origin 不允许 Origin null”错误的主要内容,如果未能解决你的问题,请参考以下文章

对于从文件:// URL 运行的应用程序发出的请求,“Access-Control-Allow-Origin 不允许 Origin null”错误

从文件:// URL 运行的应用程序发出的请求“Access-Control-Allow-Origin 不允许 Origin null”错误

从文件:// URL 运行的应用程序发出的请求“Access-Control-Allow-Origin 不允许 Origin null”错误

通知服务扩展 - 在应用程序未运行时发出 URL 请求

Spring Security 禁用从某个 url 发出的请求的安全性

SVN over HTTPS:如何隐藏或加密URL?