分析
W3C 提案Cross-Origin Resource Sharing(CORS),這份文件裡面提到,可以透過文件Header 設定可存取網域限制,以及存取方法、時間等,限制的部份有幾個:
- 必須為http, https
- 傳送資料方式為GET, POST
- 資料格式為application/xml
透過剛才的CORS,發展出更高層級XMLHttpRequest,W3C裡面也有實現方式XMLHttpRequest Level 2草案,裡面的這一段介紹:
The XMLHttpRequest Level 2 specification enhances the XMLHttpRequest object with new features, such as cross-origin requests, progress events, and the handling of byte streams for both sending and receiving.
XMLHttpRequest Level 2,可以支援cross-domain 請求,這個部份符合我們的需求。與CORS結合之後,似乎就可以ajax 跨網域存取,感覺不賴。
IE呢?
IE8以上有類似XMLHttpRequest Level 2的物件,稱為XDomainRequest,在
XDomainRequest - Restrictions, Limitations and Workarounds這篇文章裡面仔細描述如何搭配CORS原則完成跨網域的實做。
XDomainRequest - Restrictions, Limitations and Workarounds這篇文章裡面仔細描述如何搭配CORS原則完成跨網域的實做。
實做
準備請求網頁,header 就遵守CORS的規範編寫,範例為cross.php
<?php
header("Access-Control-Allow-Origin: http://clonn.info");
echo "hello cross domain.";
?>
Header 的部份宣告Access-Control-Allow-Origin,並且限制可存取網域為http://clonn.info,如果希望所有網站都可以存取可以使用"*"
接著準備一個十分基本的html 網頁,裡面的Javascript 就是這場重頭戲。
function createCORSRequest(method, url){
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr){
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined"){
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
var request = createCORSRequest("get", "http://60.248.47.246/demo/crossDomain/cross.php");
if (request){
request.onload = function(){
alert(request.responseText);
};
request.send();
}
這邊會向cross.php頁面請求,主要的請求在createCORSRequest 裡面,要檢查瀏覽器是否支援XMLHttpRequest Level 2 ,可藉由檢查物件裡是否預設有withCredentials屬性做為判斷,IE的部份檢查是否有XDomainRequest object。
藉由這個方法就能夠達到跨網域的存取。
線上模擬
Live demo
請求的頁面,回應畫面如下
跨網域存取要求發送之後,會顯示網頁如下
的確,我們做出跨網域請求,同時也將頁面的資料完成呈現,成功!
後記
很多時候都是站在前人的肩膀上看世界,才發現自己如此的渺小,跨網域存取的方式之前只知道iframe 或者是使用flash,如果不考慮IE 7的話,實際上以CORS原則的Ajax 跨網域存取是個不錯的解決方案。
參考資料
- http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
- http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/


0 意見:
張貼意見