CORS的使用
CORS要前后端同時做配置。
1、首先我們來看前端。
純js的ajax請求。
<script type="text/javascript">
? ? var xhr = new XMLHttpRequest(); //ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判斷。
? ? xhr.open(" GET", "/haorooms",true);
? ? xhr.send();
</script>
以上的haorooms是相對路徑,如果我們要使用CORS,相關Ajax代碼可能如下所示:
<script type="text/javascript">
? ? var xhr = new XMLHttpRequest();//ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判斷。
? ? xhr.open(" GET", "http://www.haorooms.com/CORS",true);
? ? xhr.send();
</script>
當然,你也可以用jquery的ajax進行。
2、后端或者服務器端的配置
下面我們主要介紹Apache和PHP里的設置方法。
Apache:Apache需要使用mod_headers模塊來激活HTTP頭的設置,它默認是激活的。你只需要在Apache配置文件的 < Directory >, < Location>, < Files >或< VirtualHost>的配置里加入以下內(nèi)容即可:
Header set Access-Control-Allow-Origin *?
PHP:只需要使用如下的代碼設置即可。
<?php?
header("Access-Control-Allow-Origin:*");?
以上的配置的含義是允許任何域發(fā)起的請求都可以獲取當前服務器的數(shù)據(jù)。當然,這樣有很大的危險性,惡意站點可能通過XSS攻擊我們的服務器。所以我們應該盡量有針對性的對限制安全的來源,例如下面的設置使得只有www.haorooms.com這個域才能跨域訪問服務器的API。
Access-Control-Allow-Origin: http://www.haorooms.com
來自 <http://www.haorooms.com/post/js_kuayu_service>
通過jsonp跨域
jsonp跨域也需要前后端配合使用。一般后端設置callback ,前端給后臺接口中傳一個callback 就可以。
例如前端代碼:
<script type="text/javascript">
? ? function dosomething(jsondata){
? ? ? ? //處理獲得的json數(shù)據(jù)
? ? }
</script>
<script src="http://haorooms.com/data.php?callback=dosomething"></script>
后臺代碼:
<?php
$callback = $_GET['callback'];//得到回調(diào)函數(shù)名
$data = array('a','b','c');//要返回的數(shù)據(jù)
echo $callback.'('.json_encode($data).')';//輸出
?>
假如你用ajax方式進行jsonp跨域,我之前的一篇文章中提及過:http://www.haorooms.com/post/jquery_ajax_wg
/*?
//簡寫形式,效果相同?
$.getJSON("url跨域地址",? {參數(shù),要把callback作為參數(shù)傳到后端},
? ? ? ? function(data){?
? ? ? ? ? ? //結(jié)構(gòu)處理
},"jsonp");?
*/?
$.ajax({?
? ? type : "get",?
? ? url : "跨域地址",?
? ? dataType : "jsonp",//數(shù)據(jù)類型為jsonp?
? ? jsonp: "callback",//服務端用于接收callback調(diào)用的function名的參數(shù)【后臺接受什么參數(shù),我們就傳什么參數(shù)】我們上面設置是callback
? ? success : function(data){?
? ? ? ? //結(jié)果處理
? ? },?
? ? error:function(data){?
? ? ? ? ? console.log(data);
? ? }?
});
來自 <http://www.haorooms.com/post/js_kuayu_service>
通過修改document.domain來跨子域
我們只需要在跨域的兩個頁面中設置document.domain就可以了。修改document.domain的方法只適用于不同子域的框架間的交互。
例如:1.在頁面 http:// www.haorooms.com/a.html 中設置document.domain
<iframe id = "iframe" src="http://haorooms.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
? ? document.domain = 'haorooms.com';//設置成主域
? ? function test(){
? ? ? ? alert(document.getElementById(' iframe').contentWindow);//contentWindow 可取得子窗口的 window 對象
? ? }
</script>
2、在頁面http:// haorooms.com/b.html 中設置document.domain
<script type="text/javascript">
? ? document.domain = 'haorooms.com';//在iframe載入這個頁面也設置document.domain,使之與主頁面的document.domain相同
</script>
來自 <http://www.haorooms.com/post/js_kuayu_service>
使用window.name來進行跨域
原理:
window對象有個name屬性,該屬性有個特征:即在一個窗口(window)的生命周期內(nèi),窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權(quán)限,window.name是持久存在一個窗口載入過的所有頁面中的。
方法:
假如有三個頁面。
a.com/app.html:應用頁面。
a.com/proxy.html:代理文件,一般是一個沒有任何內(nèi)容的html文件,需要和應用頁面在同一域下。
b.com/data.html:應用頁面需要獲取數(shù)據(jù)的頁面,可稱為數(shù)據(jù)頁面。
1、在應用頁面(a.com/app.html)中創(chuàng)建一個iframe,把其src指向數(shù)據(jù)頁面(b.com/data.html)。
數(shù)據(jù)頁面會把數(shù)據(jù)附加到這個iframe的window.name上,data.html代碼如下:
<script type="text/javascript">
? ? window.name = 'I was there!';? ? // 這里是要傳輸?shù)臄?shù)據(jù),大小一般為2M,IE和firefox下可以大至32M左右
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 數(shù)據(jù)格式可以自定義,如json、字符串
</script>
2、在應用頁面(a.com/app.html)中監(jiān)聽iframe的onload事件,在此事件中設置這個iframe的src指向本地域的代理文件(代理文件和應用頁面在同一域下,所以可以相互通信)。
app.html部分代碼如下:
<script type="text/javascript">
? ? var state = 0,
? ? iframe = document.createElement('iframe'),
? ? loadfn = function() {
? ? ? ? if (state === 1) {
? ? ? ? ? ? var data = iframe.contentWindow.name;? ? // 讀取數(shù)據(jù)
? ? ? ? ? ? alert(data);? ? //彈出'I was there!'
? ? ? ? } else if (state === 0) {
? ? ? ? ? ? state = 1;
? ? ? ? ? ? iframe.contentWindow.location = "http://a.com/proxy.html";? ? // 設置的代理文件
? ? ? ? }?
? ? };
? ? iframe.src = 'http://b.com/data.html';
? ? if (iframe.attachEvent) {
? ? ? ? iframe.attachEvent('onload', loadfn);
? ? } else {
? ? ? ? iframe.onload? = loadfn;
? ? }
? ? document.body.appendChild(iframe);
</script>
3、獲取數(shù)據(jù)以后銷毀這個iframe,釋放內(nèi)存;這也保證了安全(不被其他域frame js訪問)。
<script type="text/javascript">
? ? iframe.contentWindow.document.write('');
? ? iframe.contentWindow.close();
? ? document.body.removeChild(iframe);
</script>
來自 <http://www.haorooms.com/post/js_kuayu_service>