跨域,在平常工作中經常遇到,也經常被一些人問到跨域的處理方式。雖然處理跨域的幾種方式都有用過,但是每次提到跨域的時候經常暈乎一下先,所以在這里總結一下平時用過的幾種跨域方式
1、通過jsonp跨域在js中,我們直接用XMLHttpRequest請求不同域上的數據是不可以的,而在html中,能夠實現跨域的就幾種: - link屬性(css)
- href屬性(a標簽)
- src(img標簽、script標簽)
為了解決跨域的問題,結合script能夠發起跨域請求的原理,產生了jsonp,即:動態的創建script標簽,跨域的地址加上需要傳送的數據和回調函數為script標簽的src地址,執行完之后再動態的刪除之前創建的script. 理解了原理之后,就很容易明白jsonp的缺點了: - 只能用get方式請求,因為是使用src來傳送數據
- 數據中出現中文需要編碼。因為通過url傳參數,可以在瀏覽器輸入地址并帶上中文參數試試
- src對請求的地址沒有限制,會出現安全性的問題
2、document.domain看到這個跨域方式,可能有些同學會覺得陌生,其實這個也很常用。 每次遇到有需要使用登錄之類的項目,在開發的時候都需要將地址改成163的域名,為啥?在控制臺打印一下document.domain試試,這篇文章的控制臺輸出的是feg.netease.com,而在有使用到163登錄的項目中,輸出的都是163.com。登錄組件限制在163域名下才能用,但是163的域名有很多,避免不同域名之間出現通信問題,使用document.domain的方式將頁面的主域名改成了163.com。這種方式主要用在主域名能設置成相同的頁面之間的通信。如http://xyq.163.com/,它的主域名可以是xyq.163.com或163.com;http://xsd.163.com,它的主域名可以是xsd.163.com或163.com,所以這兩個站點下的頁面能夠將主域名設置成163.com。 3、window.name的方式這種方式利用了window對象name屬性的特征:在一個窗口(window)的生命周期內,窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的所有頁面中的,并不會因新頁面的載入而進行重置。 使用window.name還需要使用iframe來實現,下面是頁面和投票系統使用window.name方式實現的例子(投票地址:http://cgi.mmog.163.com:8088/v4a/show_vote/1250/): 頁面的js: 1 2 3 4 5 6 7 8 9 10 11 12 | var _cdkey = $( "#enter-cdkey .code-input" ).val(),
_urs = $( "#enter-cdkey .mail-input" ).val(),
_phone = $( "#enter-cdkey .phone-input" ).val();
var _windowName = _urs + "/" + _cdkey + "/" + _phone;
var _iframe = $( "iframe" );
_iframe.attr( 'src' , '' );
_iframe.attr( 'style' , 'display:none' );
_iframe.appendTo( 'body' );
_iframe[0].contentWindow.name = _windowName;
|
投票系統頁面中處理window.name傳過來的數據: 1 2 3 4 5 6 | var _urs = window.name.split( '/' )[0],
_cdkey = window.name.split( '/' )[1],
_phone = window.name.split( '/' )[2];
$( '#voterinfo_10' ).val(_urs);
$( '#voterinfo_70' ).val(_cdkey);
$( '#voterinfo_41' ).val(_phone);
|
上面只是個簡單的示例,大家有興趣可以去嘗試一下。 使用window.name方式對數據有一個限制:像上面例子示例的那樣,數據是string。 4、Access-Control-Allow-Origin方式正常情況下我們的接口都是jsonp的格式,可是萬一遇到其它格式的接口怎么辦?比如json格式,這個時候可以通過Access-Control-Allow-Origin來實現跨域。這種方式主要是后臺同學配置,接口使用Access-Control-Allow-Origin設置對應項目的域名,前端同學這邊像平常調用接口一樣,不需要再做其他處理。如下面的例子: 1 2 3 4 5 6 7 8 9 10 | $.ajax({
type: "POST" ,
data: JSON.stringify(postData),
dataType: "application/json" ,
headers: { "X-Ypw-Token" : user_token, "Content-Type" : "application/json" },
success: function (result) {
renderPage(result);
}
});
|
data為需要傳輸的數據,dataType是接口的格式。比平常接口調用多了的headers部分,是這個接口考慮到安全性的問題,接口開發同學需要我添加一個key,并且把user_token用base64加密之后傳輸給他,并不是跨域需要設置的東西,即這種方式跟平常調用接口一樣。 好像這種方式挺好用的。確實,可是最大的問題是ie7、8、9都還不支持,所以目前也就能用在移動端了。 5、--allow-file-access-from-files --disable-web-security方式這種方式是谷歌瀏覽器里面設置的,讓瀏覽器允許跨域,如圖
 除了上面的設置方式之外,還可以通過cmd命令來啟動,像平常用fis啟動項目一樣,先進入谷歌的安裝路徑,然后輸入--allow-file-access-from-files命令來啟動谷歌。之后在谷歌瀏覽器下則不需要考慮接口這些跨域的問題,像4中代碼展示差不多,直接調用接口就可以了。 這種方式好像也很方便,但實際上平常開發的時候很少用到,因為除了限制在谷歌瀏覽器之外,即使是谷歌用戶都不會去設置這個屬性。我也是因為之前開發手游管理系統的時候用到了,因為最后系統上線的時候,整個系統都在一個服務器上,沒有跨域的問題,但是開發過程中接口都放在各位開發同學的電腦上,開發過程中跨域了,所以使用了這種方式來處理。
|