JS跨域知識整理

來源:互聯網
上載者:User

標籤:style   blog   http   color   java   os   使用   io   strong   

在“跨域”一詞經常性地出現以前,我們其實已經頻繁地使用它了。如在A網站的img,src指向B網站的某一圖片地址,毫無疑問,這在通常情況下都是能正常顯示的(且不論防盜鏈技術);同樣,可以使script標籤的src屬性指向其它網站的指令碼資源(在某些情況下甚至鼓勵這樣做,以便充分利用其它網站的負載優勢,減小自身伺服器的並發量)。然而,如若使用js去主動請求其它網站的資料,比如ajax方式,就會遇到讓人鬱悶的跨域問題,這也是我們平常所說的跨域。由於安全原因,跨域訪問是被各大瀏覽器所預設禁止的。這裡涉及到同源策略的概念:同源策略阻止從一個域上載入的指令碼擷取或操作另一個域上的文件屬性。也就是說,受到請求的 URL 的域必須與當前 Web 頁面的域相同。這意味著瀏覽器隔離來自不同源的內容,以防止它們之間的操作。

跨域帶來的具體安全問題博主沒有深究,大夥可以自行腦補。

然而,很多情況下,特別是在互連網持續發展的今天,我們需要請求來自不同夥伴或資料供應商的前端介面,在跨域訪問的方式沒有正常化前(client端跨域訪問的需求看來也引起w3c的注意了,看資料說html5 WebSocket標準支援跨域的資料交換,應該也是一個將來可選的跨域資料交換的解決方案),有什麼方法能繞過它的限制呢?答案有很多(雖然都很麻煩),最常用的當屬所謂的JSONP跨域了。

JSONP原理

JSONP的最基本的原理是:動態添加一個<script>標籤,而script標籤的src屬性是沒有跨域的限制的。這樣說來,這種跨域方式其實與ajax XmlHttpRequest協議無關了。

JSONP即JSON with Padding。由於同源策略的限制,XmlHttpRequest只允許請求當前源(網域名稱、協議、連接埠)的資源。如果要進行跨域請求, 我們可以通過使用html的script標記來進行跨域請求,並在響應中返回要執行的script代碼。 這種跨域的通訊方式稱為JSONP。

來個簡單的例子:

 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">   2 <html xmlns="http://www.w3.org/1999/xhtml" >   3 <head>   4     <title>Test Jsonp</title>   5     <script type="text/javascript">   6             function jsonpCallback(result)   7             {   8             alert(result.msg);   9             }  10         </script>  11     <script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback"></script>  12 </head>  13 <body>  14 </body>  15 </html>   

簡述原理與過程:首先在用戶端註冊一個callback, 然後把callback的名字傳給伺服器(這裡用戶端和伺服器約定以key為jsonp的查詢字串值傳遞)。此時,伺服器先產生 json 資料。 然後以 javascript 文法的方式,產生一個function , function 名字就是傳遞上來的參數 jsonp。最後將 json 資料直接以入參的方式,放置到 function 中,這樣就產生了一段 js 文法的文檔,返回給用戶端。用戶端瀏覽器,解析script標籤,並執行返回的 javascript 文檔,即執行了預定義的callback函數。

從上述簡述可以推出:除了返回函數形式的js程式碼片段,服務端自然能返回所有符合規範的可執行js片段。

JSONP的缺點是:它只支援GET請求而不支援POST等其它類型的HTTP請求;它只支援跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題。(下面還有)

jQuery的Jsonp

如前所述,jsonp並非ajax請求,但是jQuery仍提供與jQuery.ajax一致的方式進行跨域請求:

$.ajax({    url: ‘http://crossdomain.com/jsonServerResponse‘,    type: ‘GET‘,    dataType: ‘jsonp‘,    jsonp: "callback",    jsonpCallback: ‘functionName‘,    success: function (data, textStatus, jqXHR) { }    //……});

如上所示,dataType設為jsonp表示這是一次跨域請求,jsonp設為服務端預定的傳遞函數名稱的查詢字串key,而jsonpCallback即為js函數名稱;假如jsonpCallback不設定,那麼jQuery將自動產生的隨機函數名(在window對象中載入一個全域的函數,當代碼插入時函數執行,執行完畢後就會被移除),可推斷該自動產生的函數會回調上述代碼中的success函數。(當手動為jsonpCallback賦值時,不知道success函數會否回調,還是說jQuery會尋找預定義的函數,若找不到則報錯?博主懶,以後再試吧。)當然jQuery為我們提供了一個簡易版本,$.getJSON,這裡就不贅述了。

需要注意的是success函數中的jqXHR參數,在ajax請求中,它是正宗的jqXHR對象,亦可看作是XMLHTTPRequest對象(繼承or封裝),但是在jsonp請求中卻並非如此,幾乎不能帶給我們如XMLHTTPRequest中最有用的那些資訊:它缺少XMLHTTPRequest的請求狀態資訊,所以並不能觸發絕大部分的回呼函數,比如error、complete等(jQuery1.9.0),而可以被回調的success函數推測應該是由script標記的load事件觸發,這也同ajax依靠XMLHTTPRequest的狀態的機制完全不同。經實驗,脫胎於jQuery的zepto(v1.1.3),在jsonp請求出現錯誤,比如載入js文檔時頭部返回401錯誤時,error函數會執行,但是該函數的jqXHR參數也同樣不是正宗的jqXHR類型,甚至不能通過它擷取響應的頭部資訊,在這種情況下,我們只是被告知某個環節出錯了,卻並不知道具體的錯誤資訊。類似回應標頭承載有用資訊的情境,博主不建議使用jsonp,可以說,使用jsonp的一個前提是:除了網路異常等非業務異常外,所有業務異常(概括地說,乃是從伺服器接收請求到返迴響應這段時間內拋出的所有異常)都需要以請求結果的形式直接返回給用戶端,便於用戶端回調分析。

 

參考資料:

JSONP跨域的原理解析

jQuery.ajax()

 

轉載請註明本文出處:http://www.cnblogs.com/newton/p/3930474.html

JS跨域知識整理

聯繫我們

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