同源與跨域之間其實(shí)有著相互制約的作用。它們從字面上看起來像兩個(gè)反義詞,但不能簡單地當(dāng)成一個(gè)反義詞去處理。在介紹跨域問題之前,先來解釋一下同源和同源策略。
同源就是如果兩個(gè)URL的協(xié)議、域名和端口相同,那么就認(rèn)為它們是同源的,3個(gè)元素缺一不可。當(dāng)一個(gè)請(qǐng)求url的協(xié)議、域名、端口三者之間任意一個(gè)與當(dāng)前頁面url不同即為跨域。
同源策略是由瀏覽器實(shí)現(xiàn)的,限制了不同源之間的交互。這種限制主要是針對(duì)一些特殊的請(qǐng)求,如不同源訪問document的限制、Ajax(XMLHttpRequest)請(qǐng)求限制等。
并不是每個(gè)不同源的請(qǐng)求都會(huì)被限制的,包括如下請(qǐng)求。
(1)頁面中的鏈接、重定向和表單提交不會(huì)受到同源策略的限制。
(2)跨域資源嵌入是允許的,當(dāng)然,瀏覽器會(huì)限制JavaScript的讀寫。
但互聯(lián)網(wǎng)的發(fā)展趨勢(shì)是越來越開放了,跨域訪問的需求也變得越來越迫切。
所以,Web開發(fā)人員就會(huì)想出一些“合法”的跨域技術(shù),來進(jìn)行不同源之間的訪問,如jsonp、iframe跨域技巧。
1. DOM的同源策略
瀏覽器的同源策略限制了來自不同源的“document”或腳本,對(duì)于當(dāng)前document的讀取或設(shè)置某些屬性,從一個(gè)域上加載的腳本不允許訪問另一個(gè)域的文檔屬性。此策略是基于DNS域名的,而不是實(shí)際的IP地址,由此會(huì)產(chǎn)生一些漏洞,如DNS重綁定攻擊,當(dāng)然,瀏覽器也會(huì)有相應(yīng)的對(duì)策,如DNS Pinning。
2. Ajax跨域
由于瀏覽器的同源策略,Ajax 的請(qǐng)求也會(huì)被限制。Ajax通過XMLHttpRequest能夠與遠(yuǎn)程的服務(wù)器進(jìn)行信息交互,另外,XMLHttpRequest是一個(gè)純粹的JavaScript對(duì)象,這個(gè)交互過程在后臺(tái)進(jìn)行,不易被察覺。
所以,實(shí)際上 JavaScript 已經(jīng)突破了原有的 JavaScript 同源策略。如果我們既想利用XMLHTTP 的無刷新異步交互能力,又不愿意公然突破 Javascript 的安全策略,可以選擇的方案就是為XMLHTTP加上嚴(yán)格的同源限制。這樣的安全策略,很類似于Applet的安全策略。iframe的限制還僅是不能訪問跨域HTMLDOM中的數(shù)據(jù),而XMLHTTP則從根本上限制了跨域請(qǐng)求的提交。
隨著Ajax技術(shù)和網(wǎng)絡(luò)服務(wù)的發(fā)展,對(duì)跨域的要求也越來越強(qiáng)烈。
3. Web Storage同源策略
隨著 Web 應(yīng)用的發(fā)展,客戶端的本地存儲(chǔ)使用得也越來越多。最簡單而且兼容性最佳的方案是 Cookie。但是在實(shí)際應(yīng)用中,Cookie 在應(yīng)用上存在很多的缺陷。所以,另一種方式是使用Web Storage。Web Storage中可以存儲(chǔ)比較簡單的key-value的鍵值對(duì)的形式的數(shù)據(jù)。
Web Storage實(shí)際上由兩部分組成:Session Storage和Local Storage。Session Storage用于存儲(chǔ)一個(gè)會(huì)話中的數(shù)據(jù),關(guān)閉瀏覽器時(shí)就會(huì)失效,而Local Storage會(huì)一直存在,用于持久性的存儲(chǔ),除非主動(dòng)刪除數(shù)據(jù),否則會(huì)一直存在。
而Web Storage也受到瀏覽器的同源策略的限制。瀏覽器會(huì)為每個(gè)域都分配存儲(chǔ)空間,不同的域之間不能進(jìn)行數(shù)據(jù)訪問。但如果域A中的腳本嵌入域B時(shí),那么瀏覽器是允許數(shù)據(jù)之間的訪問的。
4. Cookie安全策略
Cookie的同源策略與上述同源策略有一點(diǎn)不同。Cookie中的同源只關(guān)注域名,而會(huì)忽略端口和協(xié)議。例如,http://www.tjdsmy.cn calhost:8080/與http://www.tjdsmy.cn calhost:8081/的Cookie是可以共享的。