javascript跨域

更多詳情見http://blog.zhangbing.club/Ja...javascript

最近在項目開發的過程當中遇到一些Javascript 跨域請求的問題,今天抽空對其進行總結一下,以備後用,也但願同窗們在遇到相似問題的時候能夠有所幫助。html

Javascript跨域問題是web開發人員最常碰到的一個問題之一。所謂Javascript跨域問題,是指在一個域下的頁面中經過js訪問另外一個不一樣域下的數據對象,出於安全性考慮,幾乎全部瀏覽器都不容許這種跨域訪問,這就致使在一些ajax和iframe應用中,使用跨域的web service會成爲一個問題。前端

javascript跨域圖表

那到底什麼是跨域,簡單地理解就是由於JavaScript同源策略的限制,a.com 域名下的js沒法操做b.com或是c.a.com域名下的對象。更詳細的說明能夠看下錶:java

跨域圖表

特別注意兩點:jquery

  • 第一,若是是協議和端口形成的跨域問題「前臺」是無能爲力的,
  • 第二:在跨域問題上,域僅僅是經過「URL的首部」來識別而不會去嘗試判斷相同的ip地址對應着兩個域或兩個域是否在同一個ip上。

「URL的首部」指window.location.protocol +window.location.host,也能夠理解爲「Domains, protocols and ports must match」(本段來自網絡,我的以爲這段對js跨域描述得在清晰不過了)。跨域請求無處不在,平時咱們在開發活動過程當中,活動靜態頁面經過Javascript訪問前端CGI就是明顯的主域相同,子域不一樣的跨域例子,通常活動靜態頁面都是相似這樣的(http://業務名.xx.com/act/活動...,前端CGI 是這樣的(http://www.xx.com/act/活動目... 下面來看看咱們都是如何處理跨域請求的:web

動態建立script

雖然瀏覽器默認禁止了跨域訪問,但並不由止在頁面中引用其餘域的JS文件,script標籤的src屬性引用指向接收方的一個處理地址(後臺),該地址返回的javascript方法會被執行,另外URL中能夠傳入一些參數,該方法只支持GET方式提交參數。咱們經常使用FloadJS方法用的就是這種跨域方式。ajax

alt text

使用Jquery中getScript和getJson方法實現跨域

Jquery 的getScript 和 getJson方法均可以調用跨域的js或服務端腳本,可是它們的實現原理不同。json

1.getScript 方法
語法:jQuery.getScript(url,success(response,status))
該函數是簡寫的 Ajax 函數,等價於:跨域

$.ajax({
  Type: get,
  url: url,
  dataType: "script",
  success: success
});

jQuery 1.2 版本以前,getScript 只能調用同域 JS 文件。 1.2中,您能夠跨域調用 JavaScript 文件。注意:Safari 2 或更早的版本不能在全局做用域中同步執行腳本。若是經過 getScript 加入腳本,請加入延時函數。瀏覽器

實現跨域的原理:經過 GET 方式請求載入並執行一個 JavaScript 文件, 至關於經過src的形式的導入一個外部的js

2.getJson方法
語法:jQuery.getJSON(url,data,success(data,status,xhr))
該函數是簡寫的 Ajax 函數,等價於:

$.ajax({
  url: url,
  data: data,
  success: callback,
  dataType: json
});

在jQuery 1.2 中,您能夠經過使用 JSONP 形式的回調函數來加載其餘網域的 JSON 數據,如 "myurl?callback=?"。jQuery 將自動替換 ? 爲正確的函數名,以執行回調函數。

實現跨域的原理:採用Jsonp原理實現跨域

到這裏你們有沒有發現一個問題,好像一直都在討論http get 請求方式的跨域問題,難道post 請求就不存在跨域問題嗎?其實原生態From 表單 POST 到一個後臺處理腳本是不存在跨域問題,由於提交過程不牽涉到JS操做其它域名的對象,但是POST表單後,頁面會刷新,給用戶帶來的體驗不佳,這時咱們常常會想到用jquery ajax post 方法來提交表單, 雖然這種方式不會刷新頁面,可是會存在跨域問題。由於ajax自己其實是經過XMLHttpRequest對象來進行數據的交互,而瀏覽器出於安全考慮,是不容許js代碼進行跨域操做,進而會發警告,因此jquery ajax post 是行不通的,可能這時有人會說,用jsonp數據類型啊,可是jsonp目前只支持get請求方式,對post請求不支持。咱們在平時開發過程又不得不用post方式,由於get方式對請求的數量有大小限制,那在這種狀況下如何保證用戶良好的頁面體驗,又能解決跨域問題呢? 其實這時咱們能夠用最多見的document.domain + iframe 方式來實現。

document.domain + iframe

這種方式只適用主域名相同,子域名不一樣的情形,在咱們項目開發過程,這種方式仍是比較適用。

服務端代理

從上面的說明能夠看到,客戶端的解決方案局存在必定的侷限性,並且對於ajax跨域請求,不管兩個域是否屬於同個基礎域,都沒法在客戶端加以解決,也就是說若是咱們要想在ajax請求中訪問其餘域下的數據,就只能經過服務端進行處理了。服務端的解決方案的基本原理就是,由客戶端將請求發給本域服務器,再由本域服務器的代理來請求數據並將響應返回給客戶端。

使用HTML 5 postMessage方式

HTML5中最酷的新功能之一就是 跨文檔消息傳輸Cross Document Messaging。下一代瀏覽器都將支持這個功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已經使用了這個功能,用postMessage支持基於web的實時消息傳遞。
otherWindow.postMessage(message, targetOrigin);
otherWindow: 對接收信息頁面的window的引用。能夠是頁面中iframe的contentWindow屬性;window.open的返回值;經過name或下標從window.frames取到的值。
message: 所要發送的數據,string類型。
targetOrigin: 用於限制otherWindow,「*」表示不做限制
a.com/index.html中的代碼。
可是HTML5 在IE6, IE7瀏覽器下不兼容,目前移動端解決跨域問題用得比較多, PC機上用得比較少。

使用flash

若是你要讀取一個外部文件,好比swf,picture,mp3等等,那麼就須要一個跨域策略文件,allow-access-from domain表示容許訪問的URl,若是有多個依次添加,若是容許全部就一個 allow-access-from domain = "*"就能夠了。

我的小結

在項目開發過程若是能用get方式解決的就儘可能使用它,畢竟get的性能也比post高,並且處理get跨域請求的方法也比較多,好比用jquery庫的 getScript和getJson方法。若是提交的數據比較大,必定用post方式提交,而且考慮用戶的功能體驗,能夠用document.domain + iframe的方式來處理。

相關文章
相關標籤/搜索