我正在开发一个用于移动设备的Web应用程序,jsonp对于跨域请求非常酷,但是服务器的API不支持回调参数。所以我只能使用 json 从远程服务器获取数据。
我在jQuery中尝试了json,似乎它不支持跨域请求。我在 safari 上尝试了原始 ajax 请求函数,它在跨域上运行良好,那么我可以在 jQuery 中消除 json 请求的跨域限制吗?(不是 jsonp,只有 json),怎么做?
或者是否有任何替代的简单 ajax 库(跨 Web 浏览器)并且可以在跨域请求上执行 json。
同源策略
您试图规避同源政策。它内置于每个浏览器中,通常不是您可以或应该想要禁用/解决方法/等的东西。它是您的网站、用户和用户的浏览器之间非常重要的安全契约。
可替代性(可能)
CORS 允许您的 Web 服务器告诉浏览器/客户端允许访问另一个域。这是通过您的 Web 服务器输出以下 HTTP 标头来完成
的 Access-Control-Allow-Origin: http://www.example.com
如果您无法控制HTTP标头,则无法使用CORS。实现这一点是特定于语言/框架的。
请注意,您应该检查以确保浏览器兼容性,因为IE8/9的支持有限。另请注意,这是一个潜在的攻击媒介。如果您不负责任地使用响应数据,它允许来自第三方站点的响应执行 XSS 攻击。
JSONP(可能)
JSONP 是一种在服务器之间传递和获取数据的巧妙方法,方法是动态添加具有等于"yoururl.com?<your parameter data>"
src
的 script
标记到您的页面。这是在没有Web代理(见下文)或小程序(Flash/Java)的情况下完成这一壮举的唯一合法方法。但是,如果您不是请求两端的提供者,则它确实存在自己的安全风险。请记住,JSONP 允许远程服务器在您的上下文中执行代码,您应该非常小心地将该权力授予谁。
"香草"AJAX(不可能)
如果您不使用 JSONP 来获取数据,那么您很可能正在尝试使用 AJAX 请求来获取数据。AJAX 请求也受同源策略的约束。JavaScript 库(例如 jQuery、Prototype、Dojo 等)不能绕过此策略作为 Ajax 请求的基本行为。但是,他们可以支持JSONP(现在还记得,不是AJAX)。
带网络代理的 AJAX (可能)
如果确实要从其他服务器请求数据,可以转发请求。主站点的服务器将充当代理。您需要向自己的服务器发出 AJAX 请求,然后该服务器端代码将向另一个域发出请求,然后通过 AJAX 调用响应将响应发送到您的脚本。
这是一种常见的模式,这里详细介绍了Web代理模式和友好的雅虎模式(但请记住,它是雅虎特定的,只是采取一般的想法)。但是,它依赖于服务器端语言。整体实现将是相同的,但是这样做的代码将根据您选择的服务器端语言(PHP,Ruby,Python,C等)而有所不同。有些语言已经有库/模块/等来支持这种模式。
闪存(可能,非默认)
处于默认状态的闪存不支持跨域请求。它可以在Flash7+中使用跨域策略文件打开,但强烈建议不要这样做。你的脚本必须与Flash API接口,这将发出请求并将数据返回到你的JavaScript。
Java Applet (可能,非默认)
Java也受到同源策略的约束,但与Flash具有类似的解决方法,如此处所述。
其他各种"黑客"
还有其他黑客攻击,但它们通常需要您控制两端或有一个商定的通信标准。例如"window.name"黑客。我不建议大多数这些方法。
其他解决方案
有人提出了另一个与此类似的问题。它概述了我没有介绍的其他一些方法: 规避同源策略的方法
最佳解决方案
- CORS - 如果您信任第三方
- 网络代理 - 如果您不这样做
您自己的域上的网络代理可以让您清理正在检索的数据,它为您的用户提供了最大的保护。但是,如果您进行零卫生检查,则不会比此处概述的任何方法更安全。如果您确实实现了某种类型的 Web 代理,请确保其请求仅限于您想要的站点。否则,您基本上将创建一个开放代理,如果发现该代理,可能会被用户滥用并使您陷入法律麻烦。
我遇到了同样的问题。试图从服务器获取 json,但我无法访问(=>没有 JSONP)。
我发现 http://benalman.com/projects/php-simple-proxy/将 php 代理添加到您的服务器并对此文件进行 ajax 调用。"要传递到远程 URL 资源的任何 GET 参数都必须在此参数中进行 urlen编码。"
$.ajax({
type: 'GET',
url:'proxy.php?url=http://anyDomain.com?someid=thispage',
dataType: "json",
success: function(data){
// success_fn(data);
},
error: function(jqXHR, textStatus, errorThrown) {
// error_fn(jqXHR, textStatus, errorThrown);
}
});
其中代理.php(来自 Ben Alman 的文件)托管在您的域中
替代方案(我发现这是第二好的):http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
一种相当俗气的方法是我在下面所做的,以便在个人项目上启用跨站点执行
请注意,这将在接收服务器上完成,而不是在发送服务器上完成
if ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') === FALSE)
die('You shouldn't be here');
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type');
如果你想让它更安全一点,你可以这样做
if ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') === FALSE)
die('You shouldn't be here');
switch($_SERVER['HTTP_ORIGIN']){
case 'domain.com':
case 'whatever.com':
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type');
}
希望这有助于我花了很长时间才弄清楚,哈哈。