JS跨域知識總結:
在「跨域」一詞經常性地出現以前,我們其實已經頻繁地使用它了。如在A網站的img,src指向B網站的某一圖片地址,毫無疑問,這在通常情況下都是能正常顯示的(且不論防盜鏈技術);同樣,可以使script標籤的src屬性指向其它網站的腳本資源(在某些情況下甚至鼓勵這樣做,以便充分利用其它網站的負載優勢,減少自身伺服器的並發量)。然而,如若使用js去主動請求其它網站的數據,例如ajax方式,就會遇到讓人鬱悶的跨域問題,這也是我們平常所說的跨域。由於安全性原因,跨網域存取是被各大瀏覽器預設禁止的。這裡涉及到同源策略的概念:同源策略阻止從一個網域上載入的腳本取得或操作另一個網域上的文件屬性。也就是說,受到請求的 URL 的網域必須與目前 Web 頁面的網域相同。這意味著瀏覽器隔離來自不同來源的內容,以防止它們之間的操作。
跨域帶來的具體安全問題部落客沒有深究,大夥可以自行腦補。
然而,很多情況下,特別是在互聯網持續發展的今天,我們需要請求來自不同合作夥伴或數據提供商的前端接口,在跨域訪問的方式沒有規範化前(client端跨域訪問的需求看來也引起w3c的注意了,看資料說html5 WebSocket標準支援跨域的資料交換,應該也是一個將來可選的跨域資料交換的解決方案),有什麼方法能繞過它的限制呢?答案很多(雖然都很麻煩),最常用的當屬所謂的JSONP跨域了。
JSONP原理
JSONP的最基本的原理是:動態添加一個<script>標籤,而script標籤的src屬性是沒有跨域的限制的。這樣說來,這種跨域方式其實與ajax XmlHttpRequest協定無關了。 </script>
JSONP即JSON with Padding。由於同源策略的限制,XmlHttpRequest只允許請求目前來源(網域名稱、協定、連接埠)的資源。如果要進行跨網域請求, 我們可以透過使用html的script標記來進行跨網域請求,並在回應中傳回要執行的script程式碼。 這種跨域的通訊方式稱為JSONP。
來個簡單的例子:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Test Jsonp</title> <script type="text/javascript"> function jsonpCallback(result) { alert(result.msg); } </script> <script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback"></script> </head> <body> </body> </html>
來個簡單的例子:
$.ajax({ url: 'http://crossdomain.com/jsonServerResponse', type: 'GET', dataType: 'jsonp', jsonp: "callback", jsonpCallback: 'functionName', success: function (data, textStatus, jqXHR) { } //…… });
rrreee
🎜🎜🎜設為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的一個前提是:除了網路異常等非業務異常外,所有業務異常(概括地說,乃是從伺服器接收請求到回傳回應這段時間內拋出的所有異常)都需要以請求結果的形式直接傳回給客戶端,以便於客戶端回呼分析。