[分享] XMLHttpRequest執行AJAX 跨網域存取

跟大家在介紹Socket.io 的時候,意外發現居然Socket.io 可以執行跨網域的存取,為什麼?這個時候問題就已經埋下,挖掘之後發現!居然是平凡無奇的XMLHttpRequest,還有針對IE做的奇怪處理,到底是怎麼辦到的?

分析
W3C 提案Cross-Origin Resource Sharing(CORS),這份文件裡面提到,可以透過文件Header 設定可存取網域限制,以及存取方法、時間等,限制的部份有幾個:

  1. 必須為http, https
  2. 傳送資料方式為GET, POST
  3. 資料格式為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.<br></br>

XMLHttpRequest Level 2,可以支援cross-domain 請求,這個部份符合我們的需求。與CORS結合之後,似乎就可以ajax 跨網域存取,感覺不賴。

IE呢?

IE8以上有類似XMLHttpRequest Level 2的物件,稱為[XDomainRequest](http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx),在 [XDomainRequest – Restrictions, Limitations and Workarounds](http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx)這篇文章裡面仔細描述如何搭配CORS原則完成跨網域的實做。
[]()
**實做**
準備請求網頁,header 就遵守CORS的規範編寫,範例為cross.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](http://clonn.info/demo/crossDomain/simple.html) 請求的頁面,回應畫面如下
[![](http://1.bp.blogspot.com/-DRpYkH8Tm3c/TluGgXbywJI/AAAAAAAANxg/GBmDOiRhDN8/s640/20110829_2.jpg)](http://1.bp.blogspot.com/-DRpYkH8Tm3c/TluGgXbywJI/AAAAAAAANxg/GBmDOiRhDN8/s1600/20110829_2.jpg)
跨網域存取要求發送之後,會顯示網頁如下
[![](http://2.bp.blogspot.com/-qlIH1R1s10M/TluHBZopbQI/AAAAAAAANxk/8j5YZrS61jw/s640/20110829_3.jpg)](http://2.bp.blogspot.com/-qlIH1R1s10M/TluHBZopbQI/AAAAAAAANxk/8j5YZrS61jw/s1600/20110829_3.jpg)
的確,我們做出跨網域請求,同時也將頁面的資料完成呈現,成功! **後記** 很多時候都是站在前人的肩膀上看世界,才發現自己如此的渺小,跨網域存取的方式之前只知道iframe 或者是使用flash,如果不考慮IE 7的話,實際上[以CORS原則的Ajax 跨網域存取](http://clonn.blogspot.com/2011/08/xmlhttprequestajax.html)是個不錯的解決方案。 **參考資料** - [http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/](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/](http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/)

CaesarChi

Web developer, focus on website fullstack, special JavaScript, and love sharing developing experience and communicate with developers. http://about.me/clonn