ajax跨域問題

來源:互聯網
上載者:User

標籤:logs   服務   父頁面   不同   代碼   class   請求   pos   資料封裝   

(一):動態指令碼注入的方法.即在頁面中動態產生<script>指令碼標籤,另其src指向其它域的js檔案(即是src屬性為不同域的URL). (一般用於不同域之間的跨域) 

      var scriptElement = document.createElement(‘script‘);

      scriptElement.src = ‘URL‘;

      document.getElementsByTagName(‘head‘)[0].appendChild(scriptElement);

     通過動態建立script標籤就可以載入其它域的js檔案,然後通過本頁面就可以調用載入後js檔案的函數,這樣做的缺陷就是不能載入其它域的文檔

     script標籤的 src屬性不一定必須是一個存在的js檔案,也可以是一個http handler的url,只要這個http handler返回的是一個text/JavaScript類型的響應就可以了

    例:

<script type="text/javascript">          var script = document.createElement("script");          function ajaxCross(){              script.type = "text/javascript";              script.src = "http://xipang.hfutonline.net/public/test";          }          window.onload = function(){              ajaxCross();              document.getElementsByTagName("head")[0].appendChild(script);          }          function getAnswer(){              console.log(date);          }          script.onload = function() {                  getAnswer();          }</script>

 

通過請求伺服器端返回的資料是var date = {}的形式;

 

      缺點:

      不能佈建要求頭資訊;

      參數傳遞也只能使用GET方式;

      不能佈建要求的逾時處理或重試,就算失敗了也不一定知道;

      必須等資料都已經返回才能訪問他們,而且不能訪問要求標頭資訊,也不能把整個響應訊息當作字串來處理;

      還有一點就是響應訊息作為指令碼標籤的源碼,必須是可執行檔javascript代碼,不能使用其它任何格式的資料

      function jsonCallback(jsonString){                //jsonCallback進行資料封裝

            var  data  =  eval(‘(‘ +jsonString +‘)‘)

            //資料處理

      }

       優點:因為響應訊息作為js執行,所以速度非常快

 

用伺服器端的XmlHttpRequest代理實現跨域訪問

我們不能在瀏覽器端直接使用AJAX來跨域訪問資源,但是在伺服器端是沒有這種跨域安全限制的。所以,我們只需要讓伺服器端幫我們完成“跨域訪問”的工作,然後在瀏覽器端用AJAX擷取伺服器端“跨域訪問”的結果就可以了。這就是所謂的在伺服器端建立一個XmlHttpRequest代理,通過這個代理來訪問其他網域名稱下的資源。將後台作為代理,每次對其它域的請求轉交給本域的後台,本域的後台通過類比http請求去訪問其它域,再將返回的結果返回給前台,這樣做的好處是,無論訪問的是文檔,還是js檔案都可以實現跨域。

 

頁面上javascript指令碼:

 

<script type="text/javascript"><!--   Var sUrl="http://Jipiao.taobao.com/proxy.do"; //本域下Proxy 位址   var callback =   {   success: function(res) { alert(res.responseText); },   failure: function(res) { alert(‘failure‘);},   argument:{}   }   YAHOO.util.Connect.asyncRequest(‘GET‘, sUrl, callback, null);   // --></script>  

 

完成域A服務端的Proxy程式(這裡假定是一個servlet),偽碼如下:

Public class Proxy extends …….{   ..doGet(……..){   HttpClient client=……;   GetMethod get=new GetMethod("www.baidu.com/xxxxx.do");//訪問域B的連結   int statusCode = client.executeMethod(get);   if (statusCode != HttpStatus.SC_OK) {   byte[] responseBody = get.getResponseBody();   String res=new String(responseBody);   Httpresponse.getWriter().write(res);//將資料返回給域A   }   }   }   

 

基於iframe實現跨域(一般用於父域子域之間的跨域)

 

基於iframe實現的跨域要求兩個域具有aa.xx.com,bb.xx.com這種特點,也就是兩個頁面必須屬於一個基礎域(例如都是xxx.com,或是xxx.com.cn),使用同一協議(例如都是 http)和同一連接埠(例如都是80),這樣在兩個頁面中同時添加document.domain,就可以實現父頁面調用子頁面的函數

頁面一:

 

<html>    <head>      <script>       document.domain = "xx.com";        function aa(){          alert("p");       }      </script>    </head>    <body>       <iframe src="http://localhost:8080/CmsUI/2.html" id="i">              </iframe>       <script>      document.getElementById(‘i‘).onload = function(){         var d = document.getElementById(‘i‘).contentWindow;         d.a();              };       </script>     </body>    </html>    

 

 

頁面二:

 

<html>     <head>      <script>        document.domain = "xx.com";        function a(){        alert("c");         }      </script>     </head>     <body>     </body>    </html>   

 

 

也可以用iframe實現不同域之間的跨域,不過比較麻煩

當兩個域不同時,如果想相互調用,那麼同樣需要兩個域都是由你來開發才可以。用iframe可以實現資料的互相調用。解決方案就是用window.location對象的hash屬性。hash屬性就是http://domian/web/a.htm#dshakjdhsjka 裡面的#dshakjdhsjka。利用JS改變hash值網頁不會重新整理,可以這樣實現通過JS訪問hash值來做到通訊。不過除了IE之外其他大部分瀏覽器只要改變hash就會記錄曆史,你在前進和後退時就需要處理,非常麻煩。不過再做簡單的處理時還是可以用的。大體的過程是頁面a和頁面b在不同域下,b通過iframe添加到a裡,a通過JS修改iframe的hash值,b裡面做一個監聽(因為JS只能修改hash,資料是否改變只能由b自己來判斷),檢測到b的hash值被修改了,得到修改的值,經過處理返回a需要的值,再來修改a的hash值(這個地方要注意,如果a 本身是那種查詢頁面的話比如http://domian/web/a.aspx?id=3,在b中直接parent.window.location是無法取得資料的,同樣報沒有許可權的錯誤,需要a把這個傳過來,所以也比較麻煩),同樣a裡面也要做監聽,如果hash變化的話就取得返回的資料,再做相應的處理。

 

      (二):“Firefox 3”中跨域XHR,是基於W3C跨網站請求。通過設定Access-Control-Allow-Origin頭部(自訂的HTTP頭部),遠端資源有權決定自身是否可以被遠程瀏覽器訪問.實現方法如下

      Access-Control-Allow-Origin:http://www.wrox.com即通過指定哪個域可以訪問該資源來實現,此頭部資訊就指定了只有www.wrox.com域才有存取權限

      Access-Control-Allow-Origin:*表明可以允許所有請求訪問當前資源

      Origin頭部包含請求頁面的頭部(協議,網域名稱,連接埠),如果伺服器確定請求被通過,會發送一個 Access-Control-Allow-Origin頭部作為響應發送請求的同一個源,若為一個公用資源則返回 Access-Control-Allow-Origin:*

     請求另一個域的資源:使用標準的XHR對象,並為open()方法傳入一個絕對URL

     var xhr = new XMLHttpRequest();

     xhr.onreadystatechange = funtion(){

           if(xhr.readyState == 4){

                 ......

           }

    };

    xhr.open(‘get‘,‘http://somewhere -else.com/page‘,true);

    xhr.send(null);

      缺點:

     不能使用setRequestHeader()設定自訂頭部

     不會發送也不會接收cookie

     getAllResponseHeaders()方法只能返回Null 字元串

     優點:跨域的XHR對象允許訪問statues和statusText屬性

     (三):IE8中的XDomainRequest對象實現跨域

     XDR對象使用方法與XHR的類似,首先建立一個XDomainRequest的執行個體,調用open(),再調用send(),但open()只接受兩個參數,即請求的類型和URL,請求返回之後會觸發load事件,響應的資料會儲存在responseText中,響應失敗就會觸發error事件,可以調用abort()來終止請求,例:

     var xdr = new XDomainRequest();

     xdr.onload = function(){alert(xdr.responseText);

     xdr.onerror = function(){alert("an error occured.")}

     xdr.timeout = 1000;  //1秒過後會觸發timeout事件

     xdr.ontimeout = function(){alert("request took too long")}

 

 xdr.open("get","http://www.somewhere-else.com/page/");     

 

 xdr.send(null);

註:

被請求的資源可以根據它認為合適的任意資料(使用者代理程式,來源頁面)來決定是否設定Access-Control-Allow-Origin頭部

cookie不會隨請求發送,也不會隨響應返回

只能佈建要求頭部資訊中的Content-Type欄位

不能訪問回應標頭部資訊

只支援GET和POST請求

只能訪問Access-Control-Allow-Origin頭部欄位設定為*的資源

所有請求都是非同步,不能建立同步請求

接受響應之後,只能訪問響應的原始文本,沒辦法確定響應的狀態代碼

ajax跨域問題

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.