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.com/path/to/file/testserver.php
使用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).");"; ?>
回声可能是错误的,这是一段时间,因为我已经使用PHP。 无论如何,你需要输出callbackName('jsonString')
注意到引号。 jQuery将传递它自己的callback名称,所以你需要从GET参数中获取。
正如Stefan Kendall 所说 , $ .getJSON()是一个简写方法,但是你需要追加'callback=?'
到url作为GET参数(是的,值是?,jQuery用自己生成的callback方法取代了这个)。
JSONP是一个不错的select,但有一个更简单的方法。 您可以简单Access-Control-Allow-Origin
在服务器上设置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 。
您可以通过添加Access-Control-Allow-Origin来通过HTTP头来控制它 。 将其设置为*将接受来自任何域的跨域AJAX请求。
使用PHP非常简单,只需将以下代码行添加到您想从域中访问的脚本中即可:
header("Access-Control-Allow-Origin: *");
不要忘记在httpd.conf中启用mod_headers模块。
你需要看看同源策略 :
在计算中,同样的起源策略是许多浏览器端编程语言(如JavaScript)的重要安全概念。 该策略允许在源自同一站点的页面上运行的脚本访问彼此的方法和属性,而不受特定的限制,但是阻止访问不同站点上的页面上的大多数方法和属性。
为了能够获得数据,它必须是:
相同的协议和主机
你需要实现JSONP来解决它。
我不得不从本地磁盘“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文件。 其他浏览器我没有testing。
- 响应文件可以是纯文本/文本,XML,JSON或其他任何东西
这里有一个jQuery ajax调用一些debugging系统的例子。
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); } });
确实,同源策略阻止JavaScript跨域进行请求,但CORS规范只允许您正在查找的那种API访问,并且受当前批次的主要浏览器支持。
了解如何为客户端和服务器启用跨源资源共享:
“跨源资源共享(CORS)是一个规范,允许真正开放跨域的开放访问。如果您提供公共内容,请考虑使用CORS打开它,以实现通用的JavaScript /浏览器访问。
这是可能的,但你需要使用JSONP,而不是JSON。 斯蒂芬的链接指出你在正确的方向。 jQuery AJAX页面有更多关于JSONP的信息。
雷米夏普有一个使用PHP的详细示例 。
我使用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传递给你的脚本。
浏览器安全防止从一个域上托pipe的页面到另一个域上托pipe的页面进行ajax调用; 这就是所谓的“ 同源政策 ”。
有几个使用JSONP的例子,包括error handling。
不过,请注意,使用JSONP时不会触发错误事件! 请参阅: http : //api.jquery.com/jQuery.ajax/或使用jsonp错误的jQuery ajax请求
从Jquery文档( 链接 ):
-
由于浏览器安全限制,大多数“Ajax”请求都受到相同的源策略的限制; 该请求无法成功从不同的域,子域或协议中检索数据。
-
脚本和JSONP请求不受相同的源策略限制。
所以我会认为你需要使用jsonp的请求。 但是还没有尝试过这个。
对于Microsoft Azure,它稍有不同。
Azure有一个特殊的CORS设置,需要设置。 这在幕后本质上是一样的,但简单地设置标题joshuarh提到是行不通的。 用于启用跨域的Azure文档可以在这里find:
https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript
在我意识到我的主机平台有这个特殊设置之前,我花了几个小时摆弄这个。
对于交叉来源的AJAX请求,请使用以下jQuery插件。 https://github.com/jinujd/jQuery-Async-Form它工作asynchronous,无需重新加载。; 这不是AJAX,但它在大多数情况下完成任务