我正在开发一个适用于移动设备的网络应用程序,jsonp非常适合跨域请求,但服务器的API不支持回调参数。所以我只能使用json从远程服务器获取数据。
我在jQuery中尝试了json,似乎它不支持跨域请求。我在safari上尝试了原始的ajax请求函数,它在跨域工作得很好,所以我可以在jQuery中删除json请求的跨域限制吗? (不是jsonp,只有json),以及如何做到这一点?
或者是否有其他简单的ajax库(跨网络浏览器),可以在跨域请求上执行json。
答案 0 :(得分:33)
同源政策
您试图规避Same Origin Policy。它内置于每个浏览器中,通常不是您可以或应该要禁用/解决方法/等等。这是您的站点,用户和用户浏览器之间非常重要的安全合同。
CORS(可能)
CORS允许您的Web服务器告诉浏览器/客户端允许访问另一个域。这是通过Web服务器输出以下HTTP标头来完成的
Access-Control-Allow-Origin: http://www.example.com
如果无法控制HTTP标头,则无法使用CORS。这个的实现是特定于语言/框架的。
请注意,您应该检查以确保browser compatibility,因为IE8 / 9的支持有限。还要注意这是一个潜在的攻击媒介。如果您不负责任地使用响应数据,它允许来自第三方站点的响应执行XSS攻击。
<强> JSONP(可能的)强>
JSONP是一种在服务器之间传递和获取数据的聪明方法,它可以向您的网页动态添加script
个src
atrribute等于"yoururl.com?<your parameter data>"
的{{1}}标记。如果没有Web代理(见下文)或applet(Flash / Java),这是完成此类专长的唯一合法方式。但是,如果您不是请求两端的提供者,它确实有自己的安全风险。请记住,JSONP允许远程服务器在您的上下文中执行代码,您应该very careful who you give that power to。
“Vanilla”AJAX(不可能)
如果您没有使用JSONP来获取数据,那么您很可能尝试使用AJAX请求来获取数据。 AJAX请求也受同源策略的约束。 JavaScript库(例如jQuery,Prototype,Dojo等)无法绕过此策略作为Ajax请求的基本行为。但是,它们可以支持JSONP(现在记住,不是AJAX)。
带Web代理的AJAX(可能)
如果您确实想要从其他服务器请求数据,则可以转发您的请求。您的主站点的服务器将充当代理。您需要向自己的服务器发出AJAX请求,然后服务器端代码将向另一个域发出请求,然后通过AJAX调用响应将响应发送到您的脚本。
这是一种常见的模式,在此详述为Web Proxy Pattern和pricture友好雅虎here (but remember it's Yahoo specific, just take the general idea)。但是,它依赖于服务器端语言。整体实现将是相同的,但是这样做的代码将根据您选择的服务器端语言(PHP,Ruby,Python,C等)而有所不同。有些语言已经有了库/模块/等来支持这种模式。
Flash(可能,非默认)
处于默认状态的Flash不支持跨域请求。它可以在Flash7 +中使用cross-domain policy files打开,但强烈反对。您的脚本必须与Flash API接口,它将发出请求并将数据返回给您。
Java Applet(可能,非默认)
Java也受到相同的原始政策的约束,但与described here on its release的Flash类似。
各种其他“黑客”
还有其他黑客,但它们通常要求您控制两端或达成一致的通信标准。例如'window.name'黑客。我不建议大多数这些方法。
其他解决方案
有人问过与此类似的另一个问题。它概述了我没有涉及的其他一些方法:Ways to circumvent the same-origin policy
最佳解决方案
您自己域中的Web代理可以让您清理正在检索的数据,它可以为您的用户提供最大程度的保护。但是,如果您进行零卫生,则不会比此处列出的任何方法更安全。如果您确实实现了某种类型的Web代理,请确保其请求仅限于您希望的站点。否则,您基本上会创建一个open proxy,如果被发现可能会被用户滥用并让您陷入法律麻烦。
答案 1 :(得分:6)
我有同样的问题。试图从服务器获取json我没有访问权限(=&gt;没有JSONP)。
我发现http://benalman.com/projects/php-simple-proxy/将php代理添加到您的服务器并对此文件执行ajax调用。 “要传递给远程URL资源的任何GET参数都必须在此参数中进行urlencoded。”
$.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);
}
});
其中proxy.php(来自Ben Alman的文件)托管在您的域中
替代方案(我发现这是第二好的): http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
答案 2 :(得分:4)
这样做的一种相当俗气的方式就是我在下面所做的,以便在个人项目上实现跨站点执行
请注意这将在接收服务器而不是发送服务器上完成
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');
}
希望这有助于我永远把它弄清楚大声笑。