閉關紀要2.不同子網域名稱之間Ajax訪問跨域問題的解決

來源:互聯網
上載者:User

        上次給我的閉關紀要開了一個頭之後,我就一直繼續閉關研究,雖然我研究的東西大多很有來頭,而且我也預計將源碼公開,可是都還沒有一個完整的東西來給大家介紹,幾天前,我在解決我的網站效能問題的時候突然有一個想法,能夠解決我一直很想解決的子網域名稱跨域的問題,覺得應該與大家分享一下,不知道有沒有人用過。

        問題描述如下:我個人使用Ajax的方式通常是調用類似Json或者Rest介面,這些介面都是通過Script標籤傳遞資料,不過這樣使用的問題在於只能通過非同步來載入資料,很多時候會造成程式架構上的不便,遠不如直接使用Xml或者文字檔的同步訪問模式(XML Http Request)來的直接,可是如果用XML Http Request的模式,就會產生跨域問題,這樣,必須要把頁面和XML服務部署在同一個網域名稱上,哪怕是同一個網域名稱的子網域名稱也不行。

        假如我希望通過Ajax的模式,由http://www.dituren.cn/ 頁面上的代碼去訪問http://51ditu.dituren.cn/  上面的XML或者文本服務,有辦法實現嗎?

        或許你認為通過頁面上設定document.domain可以解決,不過這是白費心機,我已經研究過了,這樣是行不通的!在HTML頁面上為什麼可以呢?因為兩個頁面都可以這樣設定網域名稱:document.domain='dituren.cn';這樣他們就是在同一個域了,可是頁面去訪問XML的時候,XML顯然沒有設定自己的domain的地方,因此就會產生跨域訪問,使用者得到一個“沒有許可權”的提示。

        既然是這樣,那麼我想,為什麼不在http://51ditu.dituren.cn/  上面使用一個代理頁面,設定自身的document.domain='dituren.cn',而www域下的網頁通過Iframe載入這個頁面,並且也設定自己的域,這樣的話,這兩個頁面之間的交流是暢通的,而這個代理頁面本身是在51ditu域下的,因此肯定可以訪問本域的XML服務了。

        以上想法經過我的測試(IE6,IE7,FF3),完全可用!因此假如您已經理解我的意思,或者暫時不需要此技巧,可以不再向下看了,假如您想參考我的具體使用方法,可以向下看,說不定能對您有所啟發。

        先看看代理頁面的代碼吧:

 

 1<html>
 2<head>
 3<script language="javascript">
 4    //本函數在頁面載入的時候運行
 5    function onLoad()
 6    {
 7        document.domain="dituren.cn"//設定自身的域
 8        var hash=location.hash;//父視窗會使用錨點參數傳遞一個回呼函數名稱過來
 9        if(hash&&hash.length>1)//如果回呼函數名稱存在
10        {
11            hash=hash.substring(1);
12            parent[hash](self);//調用回呼函數,通知父視窗代理已經準備好了
13        }
14    }
15    //本函數會由父視窗調用,返回一個XMLHttpRequest對象給父視窗,剩下的操作父視窗自己完成
16    function createHttpRequest()
17    {
18        if(window.XMLHttpRequest)
19        {
20            return new XMLHttpRequest();
21        }
22        else if(typeof(ActiveXObject)!="undefined")
23        {
24            return new ActiveXObject("Microsoft.XMLHTTP");
25        }
26    }
27</script>
28</head>
29<body onload="onLoad()"></body>
30</html>

 

        代碼不算複雜吧,這是一個靜態檔案現在被我部署到了http://51ditu.dituren.cn/51ditu/ajaxAgent.htm ,我的其它子域頁面上假如需要調用http://51ditu.dituren.cn/ 上面的服務,可以採用類似於以下代碼:

 

 1        window.onAgentLoaded=function(win){window.agentWindow=win;}//設定回呼函數,在被agent頁面回調的時候設定window.agentWindow變數
 2        document.domain="dituren.cn";//設定自己的域
 3        document.write('<iframe src="http://51ditu.dituren.cn/51ditu/ajaxAgent.htm#K_CPoint_AgentLoaded" style="display:none;"></iframe>');//在頁面上通過Ajax載入Agent並通過錨點將回呼函數名稱提供給Agent頁面
 4
 5        //頁面上的其它程式通過調用此函數來獲得訪問ajax的request對象
 6        function createHttpRequest()
 7        {
 8            if(window.agentWindow){return window.agentWindow.createHttpRequest();}
 9            else
10            {
11            //假如調用服務的時候AjaxAgent還沒有載入完成,這個時候怎麼辦?
12            //我的邏輯是調用本域的,因為我的服務在每個域都有部署,只是為了效能才需要調用其它域的(另外的伺服器)
13            }
14        }

 

        上面的代碼已經擷取了一個HttpRequest對象,怎麼使用就不用我在這裡說明了,總之用這個方法實現了跨子網域名稱的Ajax訪問,這是我最高興的。

        一直以來,我都希望能夠將我的頁面部署在一個很穩定的伺服器,而將一些附加的服務部署在另一個地方,因為這些附加的服務有些是很耗效能的,避免對首頁面伺服器產生比較大的影響,這次通過這個方法,我終於可以做到這個了。

        這次網站從http://www.step1.cn/ 遷移到http://www.dituren.cn/ 一個很重要的事情就是網域名稱的分拆,以前將很多的內容都部署在一個www網域名稱下,現在,被我拆成了很多子網域名稱,在後面,我會逐次的提到每個網域名稱的作用和相關的核心技術。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.