跨域稼稿, 為什么需要跨域薄榛?跨域有什么不好?怎么實(shí)現(xiàn)跨域让歼?
一蛇数、什么是跨域
只要協(xié)議、域名是越、端口有任何一個(gè)不同耳舅,都被當(dāng)作是不同的域,之間的請(qǐng)求就是跨域操作
二倚评、跨域會(huì)有什么問(wèn)題浦徊?
防止CSRF攻擊:
補(bǔ)充知識(shí),什么是CSRF攻擊天梧?
CSRF(Cross-site request forgery跨站請(qǐng)求偽造盔性,也被稱為“One Click Attack”或者Session Riding,通衬馗冢縮寫(xiě)為CSRF或者XSRF冕香,是一種對(duì)網(wǎng)站的惡意利用。盡管聽(tīng)起來(lái)像跨站腳本(XSS)后豫,但它與XSS非常不同悉尾,并且攻擊方式幾乎相左。XSS利用站點(diǎn)內(nèi)的信任用戶挫酿,而CSRF則通過(guò)偽裝來(lái)自受信任用戶的請(qǐng)求來(lái)利用受信任的網(wǎng)站构眯。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對(duì)其進(jìn)行防范的資源也相當(dāng)稀少)和難以防范早龟,所以被認(rèn)為比XSS更具危險(xiǎn)性惫霸。
為什么會(huì)出現(xiàn)CSRF攻擊猫缭?舉例說(shuō)明
比如說(shuō)有兩個(gè)網(wǎng)站A和B。你是A網(wǎng)站的管理員壹店,你在A網(wǎng)站有一個(gè)權(quán)限是刪除用戶猜丹,比如說(shuō)這個(gè)過(guò)程只需用你的身份登陸并且POST數(shù)據(jù)到http://a.com/delUser,就可以實(shí)現(xiàn)刪除操作硅卢。好現(xiàn)在說(shuō)B網(wǎng)站射窒,B網(wǎng)站被攻擊了,別人種下了惡意代碼老赤,你點(diǎn)開(kāi)的時(shí)候就會(huì)模擬跨域請(qǐng)求轮洋,如果是針對(duì)你,那么就可以模擬對(duì)A站的跨域請(qǐng)求抬旺,恰好這個(gè)時(shí)候你已經(jīng)在A站登陸了弊予。那么攻擊者在B站內(nèi)通過(guò)腳本,模擬一個(gè)用戶刪除操作是很簡(jiǎn)單的开财。面對(duì)這種問(wèn)題汉柒,有從瀏覽器解決,但個(gè)人認(rèn)為最好是從網(wǎng)站端解決责鳍,檢測(cè)每次POST過(guò)來(lái)數(shù)據(jù)時(shí)熱refer碾褂,添加accesstoken等都是好方法。
三历葛、怎么實(shí)現(xiàn)跨域訪問(wèn)正塌?
1 document.domain + iframe
基于iframe實(shí)現(xiàn)的跨域要求兩個(gè)域具有aa.xx.com,bb.xx.com這種特點(diǎn),也就是兩個(gè)頁(yè)面必須屬于一個(gè)基礎(chǔ)域(例如都是xxx.com恤溶,或是xxx.com.cn)乓诽,使用同一協(xié)議(例如都是 http)和同一端口(例如都是80),這樣在兩個(gè)頁(yè)面中同時(shí)添加document.domain咒程,就可以實(shí)現(xiàn)父頁(yè)面調(diào)用子頁(yè)面的函數(shù)鸠天,代碼如下:
頁(yè)面一在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();
};
頁(yè)面二 head添加如下
document.domain = “xx.com”;
function a(){
alert(“c”);
}
這時(shí)候父頁(yè)面就可以調(diào)用子頁(yè)面的a函數(shù),實(shí)現(xiàn)js跨域訪問(wèn)
2 Jsonp
利用script標(biāo)簽沒(méi)有跨域限制的“漏洞”(歷史遺跡罢室觥)來(lái)達(dá)到與第三方通訊的目的稠集。當(dāng)需要通訊時(shí),本站腳本創(chuàng)建一個(gè)script元素饥瓷,地址指向第三方的API網(wǎng)址剥纷,形如:script src=”http://www.example.net/api?param1=1?m2=2">
并提供一個(gè)回調(diào)函數(shù)來(lái)接收數(shù)據(jù)(函數(shù)名可約定,或通過(guò)地址參數(shù)傳遞)扛伍。
第三方產(chǎn)生的響應(yīng)為json數(shù)據(jù)的包裝(故稱之為jsonp筷畦,即json padding),形如:
callback({“name”:”hax”,”gender”:”Male”})
這樣瀏覽器會(huì)調(diào)用callback函數(shù)刺洒,并傳遞解析后json對(duì)象作為參數(shù)鳖宾。本站腳本可在callback函數(shù)里處理所傳入的數(shù)據(jù)。
過(guò)程again
① 首先我這邊客戶端有人請(qǐng)求其他網(wǎng)頁(yè)的內(nèi)容
② 本站通過(guò)script 指向?qū)Ψ降腁PI網(wǎng)址逆航,然后提供一個(gè)數(shù)據(jù)接收的回調(diào)函數(shù)
③ 第三方產(chǎn)生后的數(shù)據(jù) json并進(jìn)行包裝 jsonp json padding 調(diào)用我們的回調(diào)函數(shù) 解析數(shù)據(jù)
JSONP的優(yōu)點(diǎn)是:它不像XMLHttpRequest對(duì)象實(shí)現(xiàn)的Ajax請(qǐng)求那樣受到同源策略的限制鼎文;它的兼容性更好,在更加古老的瀏覽器中都可以運(yùn)行因俐,不需要XMLHttpRequest或ActiveX的支持拇惋;并且在請(qǐng)求完畢后可以通過(guò)調(diào)用callback的方式回傳結(jié)果。
缺點(diǎn):它只支持GET請(qǐng)求而不支持POST等其它類型的HTTP請(qǐng)求抹剩;它只支持跨域HTTP請(qǐng)求這種情況撑帖,不能解決不同域的兩個(gè)頁(yè)面之間如何進(jìn)行JavaScript調(diào)用的問(wèn)題。
3 web代理
即用戶訪問(wèn)A網(wǎng)站時(shí)所產(chǎn)生的對(duì)B網(wǎng)站的跨域訪問(wèn)請(qǐng)求均提交到A網(wǎng)站的指定頁(yè)面(Post頁(yè)面過(guò)去)澳眷,由該頁(yè)面代替用戶頁(yè)面完成交互胡嘿,從而返回合適的結(jié)果。此方案可以解決現(xiàn)階段所能夠想到的多數(shù)跨域訪問(wèn)問(wèn)題钳踊,但要求A網(wǎng)站提供Web代理的支持衷敌,因此A網(wǎng)站與B網(wǎng)站之間必須是緊密協(xié)作的,且每次交互過(guò)程拓瞪,A網(wǎng)站的服務(wù)器負(fù)擔(dān)增加缴罗,且無(wú)法代用戶保存session狀態(tài)。
4 跨域資源共享CORS
CORS(Cross-Origin Resource Sharing)跨域資源共享祭埂,定義了必須在訪問(wèn)跨域資源時(shí)面氓,瀏覽器與服務(wù)器應(yīng)該如何溝通。CORS背后的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進(jìn)行溝通蛆橡,從而決定請(qǐng)求或響應(yīng)是應(yīng)該成功還是失敗舌界。
script type=”text/javascript”
var xhr = new XMLHttpRequest();
xhr.open(“GET”, “/trigkit4”,true);
xhr.send();
/script
以上的trigkit4是相對(duì)路徑,如果我們要使用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ū)別就在于相對(duì)路徑換成了其他域的絕對(duì)路徑禀横,也就是你要跨域訪問(wèn)的接口地址。
服務(wù)器端對(duì)于CORS的支持粥血,主要就是通過(guò)設(shè)置Access-Control-Allow-Origin來(lái)進(jìn)行的柏锄。如果瀏覽器檢測(cè)到相應(yīng)的設(shè)置,就可以允許Ajax進(jìn)行跨域的訪問(wèn)复亏。
CORS與JSONP相比趾娃,無(wú)疑更為先進(jìn)、方便和可靠缔御。
① JSONP只能實(shí)現(xiàn)GET請(qǐng)求抬闷,而CORS支持所有類型的HTTP請(qǐng)求。
② 使用CORS,開(kāi)發(fā)者可以使用普通的XMLHttpRequest發(fā)起請(qǐng)求和獲得數(shù)據(jù)笤成,比起JSONP有更好的錯(cuò)誤處理评架。
③ JSONP主要被老的瀏覽器支持,它們往往不支持CORS炕泳,而絕大多數(shù)現(xiàn)代瀏覽器都已經(jīng)支持了CORS)纵诞。