跨域, 為什么需要跨域?跨域有什么不好?怎么實現(xiàn)跨域?
一、什么是跨域
只要協(xié)議、域名、端口有任何一個不同,都被當(dāng)作是不同的域,之間的請求就是跨域操作
二、跨域會有什么問題?
防止CSRF攻擊:
補充知識,什么是CSRF攻擊?
CSRF(Cross-site request forgery跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通??s寫為CSRF或者XSRF,是一種對網(wǎng)站的惡意利用。盡管聽起來像跨站腳本(XSS),但它與XSS非常不同,并且攻擊方式幾乎相左。XSS利用站點內(nèi)的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網(wǎng)站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防范的資源也相當(dāng)稀少)和難以防范,所以被認為比XSS更具危險性。
為什么會出現(xiàn)CSRF攻擊?舉例說明
比如說有兩個網(wǎng)站A和B。你是A網(wǎng)站的管理員,你在A網(wǎng)站有一個權(quán)限是刪除用戶,比如說這個過程只需用你的身份登陸并且POST數(shù)據(jù)到http://a.com/delUser,就可以實現(xiàn)刪除操作。好現(xiàn)在說B網(wǎng)站,B網(wǎng)站被攻擊了,別人種下了惡意代碼,你點開的時候就會模擬跨域請求,如果是針對你,那么就可以模擬對A站的跨域請求,恰好這個時候你已經(jīng)在A站登陸了。那么攻擊者在B站內(nèi)通過腳本,模擬一個用戶刪除操作是很簡單的。面對這種問題,有從瀏覽器解決,但個人認為最好是從網(wǎng)站端解決,檢測每次POST過來數(shù)據(jù)時熱refer,添加accesstoken等都是好方法。
三、怎么實現(xiàn)跨域訪問?
1 document.domain + iframe
基于iframe實現(xiàn)的跨域要求兩個域具有aa.xx.com,bb.xx.com這種特點,也就是兩個頁面必須屬于一個基礎(chǔ)域(例如都是xxx.com,或是xxx.com.cn),使用同一協(xié)議(例如都是 http)和同一端口(例如都是80),這樣在兩個頁面中同時添加document.domain,就可以實現(xiàn)父頁面調(diào)用子頁面的函數(shù),代碼如下:
頁面一在head內(nèi)添加js如下:
document.domain = “xx.com”;
function aa(){
? ? ? ? ? ?alert(“p”);
}
body添加iframe和js如下
iframe src=”http://localhost:8080/CmsUI/2.html“ id=”i”
document.getElementById(‘i’).onload = function(){
? ? ? ? ? ? ? ?var d = document.getElementById(‘i’).contentWindow;
? ? ? ? ? ? ? ?d.a();
};
頁面二 head添加如下
document.domain = “xx.com”;
function a(){
? ? ? ? ? ? ?alert(“c”);
}
這時候父頁面就可以調(diào)用子頁面的a函數(shù),實現(xiàn)js跨域訪問
2 Jsonp
利用script標(biāo)簽沒有跨域限制的“漏洞”(歷史遺跡?。﹣磉_到與第三方通訊的目的。當(dāng)需要通訊時,本站腳本創(chuàng)建一個script元素,地址指向第三方的API網(wǎng)址,形如:script src=”http://www.example.net/api?param1=1?m2=2">
并提供一個回調(diào)函數(shù)來接收數(shù)據(jù)(函數(shù)名可約定,或通過地址參數(shù)傳遞)。
第三方產(chǎn)生的響應(yīng)為json數(shù)據(jù)的包裝(故稱之為jsonp,即json padding),形如:
callback({“name”:”hax”,”gender”:”Male”})
這樣瀏覽器會調(diào)用callback函數(shù),并傳遞解析后json對象作為參數(shù)。本站腳本可在callback函數(shù)里處理所傳入的數(shù)據(jù)。
過程屢一下
① 首先我這邊客戶端有人請求其他網(wǎng)頁的內(nèi)容
② 本站通過script 指向?qū)Ψ降腁PI網(wǎng)址,然后提供一個數(shù)據(jù)接收的回調(diào)函數(shù)
③ 第三方產(chǎn)生后的數(shù)據(jù) json并進行包裝 jsonp json padding 調(diào)用我們的回調(diào)函數(shù) 解析數(shù)據(jù)
JSONP的優(yōu)點是:它不像XMLHttpRequest對象實現(xiàn)的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中都可以運行,不需要XMLHttpRequest或ActiveX的支持;并且在請求完畢后可以通過調(diào)用callback的方式回傳結(jié)果。
缺點:它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調(diào)用的問題。
3 web代理
即用戶訪問A網(wǎng)站時所產(chǎn)生的對B網(wǎng)站的跨域訪問請求均提交到A網(wǎng)站的指定頁面(Post頁面過去),由該頁面代替用戶頁面完成交互,從而返回合適的結(jié)果。此方案可以解決現(xiàn)階段所能夠想到的多數(shù)跨域訪問問題,但要求A網(wǎng)站提供Web代理的支持,因此A網(wǎng)站與B網(wǎng)站之間必須是緊密協(xié)作的,且每次交互過程,A網(wǎng)站的服務(wù)器負擔(dān)增加,且無法代用戶保存session狀態(tài)。
4 跨域資源共享CORS
CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務(wù)器應(yīng)該如何溝通。CORS背后的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進行溝通,從而決定請求或響應(yīng)是應(yīng)該成功還是失敗。
<script type=”text/javascript”>
var xhr = new XMLHttpRequest();
xhr.open(“GET”, “/trigkit4”,true);
xhr.send();
</script>
以上的trigkit4是相對路徑,如果我們要使用CORS,相關(guān)Ajax代碼可能如下所示:
<script type=”text/javascript”>
var xhr = new XMLHttpRequest();
xhr.open(“GET”, “http://segmentfault.com/u/trigkit4/",true);
xhr.send();
</script>
代碼與之前的區(qū)別就在于相對路徑換成了其他域的絕對路徑,也就是你要跨域訪問的接口地址。
服務(wù)器端對于CORS的支持,主要就是通過設(shè)置Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應(yīng)的設(shè)置,就可以允許Ajax進行跨域的訪問。
CORS與JSONP相比,無疑更為先進、方便和可靠。
① JSONP只能實現(xiàn)GET請求,而CORS支持所有類型的HTTP請求。
② 使用CORS,開發(fā)者可以使用普通的XMLHttpRequest發(fā)起請求和獲得數(shù)據(jù),比起JSONP有更好的錯誤處理。
③ JSONP主要被老的瀏覽器支持,它們往往不支持CORS,而絕大多數(shù)現(xiàn)代瀏覽器都已經(jīng)支持了CORS)。