jQuery跨域AJAX

这里有两个页面,test.php和testserver.php。

test.php

<script src="scripts/jq.js" type="text/javascript"></script>
<script>
$(function() {
$.ajax({url:"testserver.php",
success:function() {
alert("Success");
},
error:function() {
alert("Error");
},
dataType:"json",
type:"get"
}
)})
</script>

testserver.php

<?php
$arr = array("element1",
"element2",
array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>

现在我的问题是:当这两个文件都在同一个服务器上(本地主机或web服务器),它工作,alert("Success")被调用;如果它在不同的服务器上,即web服务器上的testserver.php和localhost上的test.php,则它不工作,并且alert("Error")正在执行。即使AJAX内部的URL被更改为http://domain.example/path/to/file/testserver.php

801430 次浏览

你需要看一下同源策略:

计算中的同源策略 一个重要的安全概念是什么 浏览器端编程的数量 语言,比如JavaScript。的 策略允许运行脚本 来自同一站点的页面 访问彼此的方法和 没有特定的属性 限制,但阻止访问 大多数方法和属性

为了让你能够获得数据,它必须是:

相同的协议和主机

你需要实现JSONP来解决它。

浏览器安全性防止ajax调用从一个域上托管的页面到另一个域上托管的页面;这被称为“同源策略”。

使用JSONP

jQuery:

$.ajax({
url:"testserver.php",
dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
success:function(json){
// do stuff with json (in this case an array)
alert("Success");
},
error:function(){
alert("Error");
}
});

PHP:

<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>

echo可能是错误的,我已经有一段时间没用php了。在任何情况下,你都需要输出callbackName('jsonString'),注意引号。jQuery会传递自己的回调名称,所以你需要从get参数中获取。

正如Stefan Kendall所发布的,$ .getJSON ()是一个简便方法,但随后你需要将'callback=?'作为GET参数附加到url(是的,value是?,jQuery用自己生成的回调方法替换此方法)。

Jquery文档(链接):

  • 由于浏览器的安全限制,大多数“Ajax”请求都遵循同源策略;请求无法成功地从不同的域、子域或协议检索数据。

  • 脚本和JSONP请求不受同源策略限制。

因此,我认为您需要使用jsonp来处理请求。但我自己还没试过。

这是可能的,但您需要使用JSONP,而不是JSON。斯特凡的线索给你指明了方向。jQuery AJAX页面有更多关于JSONP的信息。

Remy Sharp有一个使用PHP的详细示例

JSONP是一个不错的选择,但是还有一种更简单的方法。你可以简单地在你的服务器上设置Access-Control-Allow-Origin头。将其设置为*将接受来自任何域的跨域AJAX请求。(https://developer.mozilla.org/en/http_access_control)

当然,这样做的方法因语言而异。下面是Rails版本:

class HelloController < ApplicationController
def say_hello
headers['Access-Control-Allow-Origin'] = "*"
render text: "hello!"
end
end

在本例中,say_hello动作将接受来自任何域的AJAX请求,并返回“hello!”响应。

下面是它可能返回的头的一个例子:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive

尽管它很简单,但它确实有一些浏览器限制。看到http://caniuse.com/#feat=cors

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

我不得不从本地磁盘加载网页“file:///C:/test/htmlpage.html”,调用“http://localhost/getxml.php”url,并在IE8+和Firefox12+浏览器中做到这一点,使用jQuery v1.7.2 lib来最小化样板代码。在阅读了几十篇文章之后,我终于明白了。以下是我的总结。

  • 服务器脚本(.php, .jsp,…)必须返回http响应头Access-Control-Allow-Origin: *
  • 在使用jQuery ajax之前,在javascript中设置这个标志:jQuery.support.cors = true;
  • 你可以设置标志一次或每次使用jQuery ajax函数
  • 现在我可以在IE和Firefox中阅读。xml文档。其他浏览器我没有测试。
  • 响应文档可以是纯/文本,xml, json或其他任何东西

下面是一个jQuery ajax调用的例子,其中包含一些调试系统。

jQuery.support.cors = true;
$.ajax({
url: "http://localhost/getxml.php",
data: { "id":"doc1", "rows":"100" },
type: "GET",
timeout: 30000,
dataType: "text", // "xml", "json"
success: function(data) {
// show text reply as-is (debug)
alert(data);


// show xml field values (debug)
//alert( $(data).find("title").text() );


// loop JSON array (debug)
//var str="";
//$.each(data.items, function(i,item) {
//  str += item.title + "\n";
//});
//alert(str);
},
error: function(jqXHR, textStatus, ex) {
alert(textStatus + "," + ex + "," + jqXHR.responseText);
}
});

有一些使用JSONP的例子,其中包括错误处理。

但是,请注意,使用JSONP时不会触发错误事件!参见:http://api.jquery.com/jQuery.ajax/jQuery ajax请求使用jsonp错误

同源策略确实阻止了JavaScript跨域发起请求,但是CORS规范只允许您正在寻找的那种API访问,并且得到当前一批主要浏览器的支持。

查看如何为客户端和服务器启用跨源资源共享:

http://enable-cors.org/

“跨域资源共享(CORS)是一个实现跨域边界真正开放访问的规范。如果你提供公共内容,请考虑使用CORS将其开放给通用JavaScript/浏览器访问。”

你可以通过添加Access-Control-Allow-Origin来控制HTTP头。将其设置为*将接受来自任何域的跨域AJAX请求。

使用PHP真的很简单,只需在脚本中添加以下一行,你想从你的域外部访问它:

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

不要忘记在httpd.conf中启用mod_headers模块。

对于微软Azure来说,情况略有不同。

Azure有一个需要设置的特殊CORS设置。这在幕后本质上是相同的事情,但简单地设置joshua提到的头文件将不起作用。Azure支持跨域的文档可以在这里找到:

https://learn.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript

我摆弄了几个小时,才意识到我的主机平台有这个特殊的设置。

我知道3个方法来解决你的问题:

  1. 首先,如果你可以访问两个域,你可以允许访问所有其他域使用:

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

    或者只是通过在。htaccess文件中添加如下代码来创建一个域:

    < p > <代码> & lt; FilesMatch \”。(ttf |传递|测试结束| woff) $”比; & lt; IfModule mod_headers.c> SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0 头添加Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin & lt; / IfModule> 代码& lt; / FilesMatch> < / > < / p > < /李>
  2. 您可以使用ajax请求服务器中的PHP文件,并使用此PHP文件处理对另一个域的请求。

  3. 您可以使用jsonp,因为它不需要许可。你可以阅读我们的朋友@BGerrissen的回答。

它的工作,所有你需要:

PHP:

header('Access-Control-Allow-Origin: http://www.example.com');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

JS (jQuery ajax):

var getWBody = $.ajax({ cache: false,
url: URL,
dataType : 'json',
type: 'GET',
xhrFields: { withCredentials: true }
});

它在PHP中工作,只需将此添加到所服务的页面:

header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');

PS:我用方便和有用的方法制作了自己的xhr套件sa_ajax。(https://github.com/osergioabreu/sa_ajax/)