做者:Eiji Kitamura & Domenic Denicola翻譯:瘋狂的技術宅html
原文:https://web.dev/why-coop-coep/前端
未經容許嚴禁轉載git
爲何須要跨域隔離才能使用功能強大的功能,例如 SharedArrayBuffer
,performance.measureMemory()
和 JS Self-Profiling API。程序員
本文解釋了爲何須要跨域隔離才能啓用瀏覽器上的強大功能。github
關鍵術語:本文使用了許多類似的術語。爲了使事情更清楚,先讓咱們明確它們:web
Web 是基於 same-origin policy 構建的:這是一種安全功能,它是用來限制文檔和腳本如何與其餘來源的資源進行交互的。該原則限制了網站訪問跨域資源的方式。例如,來自 https://a.example
的文檔被禁止訪問 https://b.example
上託管的數據。面試
可是,在歷史上同源政策有一些例外。任何網站均可以:json
若是能夠從頭開始設計 Web,則這些異常將不存在。不幸的是,當 web 社區意識到嚴格的同源策略的優點時,web 已經開始依賴這些例外。segmentfault
這種鬆散的同源策略的安全反作用有兩種方式進行修補。一種方法是經過引入稱爲跨域資源共享(CORS)的新協議,其目的是確保服務器容許共享具備給定來源的資源。另外一種方法是經過隱式刪除對跨域資源的直接腳本訪問,同時保留向後兼容性。這樣的跨域資源稱爲「不透明」資源。這就是爲何除非把 CORS 應用於圖像,不然經過CanvasRenderingContext2D
操做跨域圖像的像素會失敗的緣由。跨域
全部這些策略決策都在同一個瀏覽上下文組中發生(browsing context group)。
長期以來,CORS 和不透明資源的結合就足夠使瀏覽器安全了。儘管有時會發現一些極端狀況(例如 JSON 漏洞)須要打補丁,但總的來講,不容許直接讀取跨域資源的原始字節的原則是成功的。
全部這些都經過 Spectre) 進行了更改,這使得加載到與代碼同一的瀏覽上下文組中的任何數據都具備可讀性。若是 evil.com
嵌入了跨域圖像,則他們能夠用 Spectre 攻擊讀取其像素數據,這使得依賴「不透明性」的保護無效。
在理想狀況下,全部跨域請求都應由擁有資源的服務器明確審覈。若是擁有資源的服務器未提供審查,則數據將永遠不會進入攻擊者的瀏覽上下文組,所以他們將不會收到 Spectre 攻擊的影響。咱們稱其爲跨域隔離狀態。這正是COOP + COEP的意義所在。
在跨域隔離狀態下,發出請求的站點被認爲不太危險,而且能夠解鎖強大的功能,例如 SharedArrayBuffer
, performance.measureMemory
和 JS Self-Profiling API,這些功能本來能夠用於相似 Spectre 的攻擊。它還防止修改 document.domain
。
跨域嵌入策略(COEP)阻止文檔加載任何未明確授予文檔許可權的跨域資源(使用CORP或CORS)。使用這個功能,你能夠聲明文檔沒法加載此類資源。
要激活此策略,須要添加如下 HTTP 頭:
Cross-Origin-Embedder-Policy: require-corp
require-corp
關鍵字是 COEP 惟一接受的值。這將強制執行如下策略:文檔只能從同一來源加載資源,或者顯式被標記爲可從另外一來源加載的資源。
爲了從其餘來源加載資源,須要支持跨域資源共享(CORS)或跨域資源策略(CORP)。
若是跨域資源支持跨域資源共享(CORS),則可使用 crossorigin
屬性將其加載到你的網頁上,而不會被 COEP 阻止。
<img src="https://third-party.example.com/image.jpg" crossorigin>
若是這個圖片資源帶有 CORS 標頭,應該用 crossorigin
屬性,以便將經過使用 CORS 模式獲取資源的請求。除非設置了 CORS 標頭,不然將會阻止圖像加載。
一樣,你能夠經過 fetch()
方法獲取跨域數據,只要服務器使用正確的 HTTP 頭進行響應,就不須要特殊處理。
跨域資源策略(CORP))最初是做爲一種選項被加入的,能夠防止你的資源被其餘域加載。在 COEP 的上下文中,CORP 能夠指定誰能夠加載資源的策略。
Cross-Origin-Resource-Policy
標頭有三個可能的值:
Cross-Origin-Resource-Policy: same-site
標記爲 same-site
的資源只能從相同站點加載。
Cross-Origin-Resource-Policy: same-origin
標有 same-origin
的資源只能從相同的來源加載。
Cross-Origin-Resource-Policy: cross-origin
被標記爲 cross-origin
的資源能夠被任何網站加載。 (這個值 與 COEP 一塊兒添加到了 CORP 規範中。)
添加 COEP 標頭後,將沒法用 service worker 來繞過限制。若是文檔受到 COEP 標頭的保護,則在響應進入文檔過程以前或在進入控制文檔的 service worker 以前,將遵照策略。
跨域開放者策略(COOP)容許你經過將其餘文檔放在不一樣的瀏覽器上下文組中,確保將其與其餘文檔隔離開,這樣它們就不能直接與頂層窗口進行交互。例如,若是帶有 COOP 的文檔打開一個彈出窗口,則其 window.opener
屬性將爲 null
。一樣,打開器引用的 .closed
屬性將返回 true
。
Cross-Origin-Opener-Policy
標頭有三個可能的值:
Cross-Origin-Opener-Policy: same-origin
標有 same-origin
的文檔能夠與標有 same-origin
的同源文件共享相同的瀏覽上下文組。
Cross-Origin-Opener-Policy: same-origin-allow-popups
帶有 same-origin-allow-popups
的頂級文檔保留了對未設置 COOP 或經過把 COOP 設置爲 unsafe-none
而選擇退出隔離的任何彈出窗口的引用。
Cross-Origin-Opener-Policy: unsafe-none
unsafe-none
是默認設置,而且容許將文檔添加到 opener 的瀏覽上下文組中,除非 opener 自己的 COOP 爲 same-origin
或 same-origin-allow-popups
。
noopener
屬性有與 COOP 相同的效果,不一樣之處在於它只能工做從 opener 那邊開始。 (當第三方打開窗口時,你不能取消它的關聯。)經過執行諸如 window.open(url, '_blank', 'noopener')
或 <a target="_blank" rel="noopener">,
之類的操做來附加 noopener
時,你能夠故意將你的窗口與打開的窗口解除關聯。
儘管 noopener
能夠用 COOP 代替,可是當你想在不支持 COOP 的瀏覽器中保護網站時,它仍然頗有用。
若是要確保訪問諸如 SharedArrayBuffer
,Performance.measureMemory
或 JS Self-Profiling API 之類的強大功能,只需記住你的文檔須要同時使用 COEP (值爲 require-corp
)和 REOP(值爲 same-origin
)。
若是二者都不存在,瀏覽器將沒法保證足夠的隔離度以安全地啓用那些強大的功能。你能夠經過檢查self.crossOriginIsolated
是否返回 true 來肯定頁面的情況。
在使用 COOP 和 COEP 使網站「跨域隔離」 一文中瞭解實現此步驟的步驟。