前端必備HTTP技能之同源策略詳解

同源策略在web應(yīng)用的安全模型中是一個(gè)重要概念。在這個(gè)策略下,web瀏覽器允許第一個(gè)頁面的腳本訪問第二個(gè)頁面里的數(shù)據(jù),但是也只有在兩個(gè)頁面有相同的源時(shí)。源是由URI,主機(jī)名,端口號組合而成的。這個(gè)策略可以阻止一個(gè)頁面上的惡意腳本通過頁面的DOM對象獲得訪問另一個(gè)頁面上敏感信息的權(quán)限。

對于普遍依賴于cookie維護(hù)授權(quán)用戶session的現(xiàn)代瀏覽器來說,這種機(jī)制有特殊意義??蛻舳吮仨氃诓煌军c(diǎn)提供的內(nèi)容之間維持一個(gè)嚴(yán)格限制,以防丟失數(shù)據(jù)機(jī)密或者完整性。

歷史

同源策略的概念要追溯到1995年的網(wǎng)景瀏覽器。同源策略作為一個(gè)重要的安全基石,所有的現(xiàn)代瀏覽器都在一定程度上實(shí)現(xiàn)了同源策略。同源策略雖然不是一個(gè)明確規(guī)范,但是經(jīng)常為某些web技術(shù)(例如Microsoft Silverlight,Adobe Flash,Adobe Acrobat)或者某些機(jī)制(例如XMLHttpRequest)擴(kuò)展定義大致兼容的安全邊界。

源決定規(guī)則

RFC6454中有定義URI源的算法定義。對于絕對的URIs,源就是{協(xié)議,主機(jī),端口}定義的。只有這些值完全一樣才認(rèn)為兩個(gè)資源是同源的。

為了舉例,下面的表格給出了與URL"http://www.example.com/dir/page.html"的對比。

對比URL 結(jié)果 結(jié)果
http://www.example.com/dir/page2.html 同源 相同的協(xié)議,主機(jī),端口
http://www.example.com/dir2/other.html 同源 相同的協(xié)議,主機(jī),端口
http://username:password@www.example.com/dir2/other.html 同源 相同的協(xié)議,主機(jī),端口
http://www.example.com:81/dir/other.html 不同源 相同的協(xié)議,主機(jī),端口不同
https://www.example.com/dir/other.html 不同源 協(xié)議不同
http://en.example.com/dir/other.html 不同源 不同主機(jī)
http://example.com/dir/other.html 不同源 不同主機(jī)(需要精確匹配)
http://v2.www.example.com/dir/other.html 不同源 不同主機(jī)(需要精確匹配)
http://www.example.com:80/dir/other.html 看情況 端口明確,依賴瀏覽器實(shí)現(xiàn)

不像其他瀏覽器,IE在計(jì)算源的時(shí)候沒有包括端口。

安全考量

有這種限制的主要原因就是如果沒有同源策略將導(dǎo)致安全風(fēng)險(xiǎn)。假設(shè)用戶在訪問銀行網(wǎng)站,并且沒有登出。然后他又去了任意的其他網(wǎng)站,剛好這個(gè)網(wǎng)站有惡意的js代碼,在后臺請求銀行網(wǎng)站的信息。因?yàn)橛脩裟壳叭匀皇倾y行站點(diǎn)的登陸狀態(tài),那么惡意代碼就可以在銀行站點(diǎn)做任意事情。例如,獲取你的最近交易記錄,創(chuàng)建一個(gè)新的交易等等。因?yàn)闉g覽器可以發(fā)送接收銀行站點(diǎn)的session cookies,在銀行站點(diǎn)域上。訪問惡意站點(diǎn)的用戶希望他訪問的站點(diǎn)沒有權(quán)限訪問銀行站點(diǎn)的cookie。當(dāng)然確實(shí)是這樣的,js不能直接獲取銀行站點(diǎn)的session cookie,但是他仍然可以向銀行站點(diǎn)發(fā)送接收附帶銀行站點(diǎn)session cookie的請求,本質(zhì)上就像一個(gè)正常用戶訪問銀行站點(diǎn)一樣。關(guān)于發(fā)送的新交易,甚至銀行站點(diǎn)的CSRF(跨站請求偽造)防護(hù)都無能無力,因?yàn)槟_本可以輕易的實(shí)現(xiàn)正常用戶一樣的行為。所以如果你需要session或者需要登陸時(shí),所有網(wǎng)站都面臨這個(gè)問題。如果上例中的銀行站點(diǎn)只提供公開數(shù)據(jù),你就不能觸發(fā)任意東西,這樣的就不會(huì)有危險(xiǎn)了,這些就是同源策略防護(hù)的。當(dāng)然,如果兩個(gè)站點(diǎn)是同一個(gè)組織的或者彼此互相信任,那么就沒有這種危險(xiǎn)了。

規(guī)避同源策略

在某些情況下同源策略太嚴(yán)格了,給擁有多個(gè)子域的大型網(wǎng)站帶來問題。下面就是解決這種問題的技術(shù):

document.domain屬性

如果兩個(gè)window或者frames包含的腳本可以把domain設(shè)置成一樣的值,那么就可以規(guī)避同源策略,每個(gè)window之間可以互相溝通。例如,orders.example.com下頁面的腳本和catalog.example.com下頁面的腳本可以設(shè)置他們的document.domain屬性為example.com,從而讓這兩個(gè)站點(diǎn)下面的文檔看起來像在同源下,然后就可以讓每個(gè)文檔讀取另一個(gè)文檔的屬性。這種方式也不是一直都有用,因?yàn)槎丝谔柺窃趦?nèi)部保存的,有可能被保存成null。換句話說,example.com的端口號80,在我們更新document.domain屬性的時(shí)候可能會(huì)變成null。為null的端口可能不被認(rèn)為是80,這主要依賴瀏覽器實(shí)現(xiàn)。

跨域資源共享

這種方式使用了一個(gè)新的Origin請求頭和一個(gè)新的Access-Control-Allow-Origin響應(yīng)頭擴(kuò)展了HTTP。允許服務(wù)端設(shè)置Access-Control-Allow-Origin頭標(biāo)識哪些站點(diǎn)可以請求文件,或者設(shè)置Access-Control-Allow-Origin頭為"*",允許任意站點(diǎn)訪問文件。瀏覽器,例如Firefox3.5,Safari4,IE10使用這個(gè)頭允許跨域HTTP請求。

跨文檔通信

這種方式允許一個(gè)頁面的腳本發(fā)送文本信息到另一個(gè)頁面的腳本中,不管腳本是否跨域。在一個(gè)window對象上調(diào)用postMessage()會(huì)異步的觸發(fā)window上的onmessage事件,然后觸發(fā)定義好的事件處理方法。一個(gè)頁面上的腳本仍然不能直接訪問另外一個(gè)頁面上的方法或者變量,但是他們可以安全的通過消息傳遞技術(shù)交流。

JSONP

JOSNP允許頁面接受另一個(gè)域的JSON數(shù)據(jù),通過在頁面增加一個(gè)可以從其它域加載帶有回調(diào)的JSON響應(yīng)的<script>標(biāo)簽。

WebSocket

現(xiàn)代瀏覽器允許腳本直連一個(gè)WebSocket地址而不管同源策略。然而,使用WebSocket URI的時(shí)候,在請求中插入Origin頭就可以標(biāo)識腳本請求的源。為了確??缯景踩琖ebSocket服務(wù)器必須根據(jù)允許接受請求的白名單中的源列表比較頭數(shù)據(jù)。

個(gè)例以及異常

在一些個(gè)例中,例如哪些沒有明確定義主機(jī)名或者端口的協(xié)議(file:,data:,等),同源檢查以及相關(guān)機(jī)制如何運(yùn)作沒有很好的定義。這在歷史上導(dǎo)致了很多安全問題,例如任意本地存儲(chǔ)的HTML文件不能訪問磁盤上的其他文件,也不能與任何網(wǎng)絡(luò)上的站點(diǎn)通信。

另外,很多遺留的跨域操作,早期是不受同源策略限制的,例如<script>的跨域請求以及表單POST提交。

最后,某些類型的攻擊,例如DNS重新綁定,服務(wù)端代理,可以破壞主機(jī)名檢查,讓流氓頁面可以直接通過地址與站點(diǎn)通信,盡管地址不是同源的。這種攻擊的影響僅限于某些特殊情況下,例如,如果瀏覽器仍然相信正在通信的攻擊者的站點(diǎn),然后沒有公開第三方cookie或者其他敏感信息給攻擊者。

變通方法

為了讓開發(fā)者可以在可控情況下繞過同源策略,一些"hacks"方法可以被用來在不同域的文檔之間傳輸數(shù)據(jù),例如fragment identifier ,window.name屬性。根據(jù)HTML5標(biāo)準(zhǔn),一個(gè)postMessage接口可以實(shí)現(xiàn)這樣的功能,但是只有最新的瀏覽器才支持。JSONP也可以用來保證通過類似Ajax的方式訪問跨域資源。

做好前端開發(fā)必須對HTTP的相關(guān)知識有所了解,所以我創(chuàng)建了一個(gè)專題前端必備HTTP技能專門收集前端相關(guān)的HTTP知識,歡迎關(guān)注,投稿。


PS:本文翻譯自維基百科,原文地址https://en.wikipedia.org/wiki/Same-origin_policy

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容