使用 COOP 和 COEP 設定跨來源隔離環境,並啟用強大的功能,例如 SharedArrayBuffer、performance.measureUserAgentSpecificMemory() 和精確度更高的精確計時器。
更新
- 2022 年 6 月 21 日:啟用跨來源隔離時,也需要注意工作人員指令碼。新增一些說明。
- 2021 年 8 月 5 日:JS Self-Profiling API 曾列為需要跨來源隔離的 API 之一,但最近的發展方向有變,因此已移除。
- 2021 年 5 月 6 日:根據收到的意見回饋和回報的問題,我們決定調整時間表,將在 Chrome M92 中限制非跨來源隔離網站的
SharedArrayBuffer用法。 - 2021 年 4 月 16 日:新增有關新的 COEP 無憑證模式的附註,並說明 COOP same-origin-allow-popups 是跨來源隔離的寬鬆條件。
- 2021 年 3 月 5 日:移除
SharedArrayBuffer、performance.measureUserAgentSpecificMemory()和偵錯功能的限制,這些功能現在已在 Chrome 89 中全面啟用。新增即將推出的功能,performance.now()和performance.timeOrigin,可提供更高的精確度。 - 2021 年 2 月 19 日:新增有關功能政策的附註,
allow="cross-origin-isolated"以及開發人員工具的偵錯功能。 - 2020 年 10 月 15 日:Chrome 87 以上版本支援
self.crossOriginIsolated。 因此,當self.crossOriginIsolated傳回true時,document.domain不可變動。performance.measureUserAgentSpecificMemory()的來源試用即將結束,且預設會在 Chrome 89 中啟用。Android 版 Chrome 的 Shared Array Buffer 將於 Chrome 88 推出。
部分網頁 API 會增加側通道攻擊 (例如 Spectre) 的風險。為降低這項風險,瀏覽器提供以選擇加入為基礎的隔離環境,稱為跨來源隔離。在跨來源隔離狀態下,網頁可以使用下列專屬功能:
| API | 說明 |
|---|---|
SharedArrayBuffer
|
WebAssembly 執行緒必須使用此函式。這項功能適用於 Android Chrome 88 以上版本。目前電腦版預設會透過 網站隔離啟用這項功能,但需要跨來源隔離狀態,且 會在 Chrome 92 版中預設停用。 |
performance.measureUserAgentSpecificMemory()
|
適用於 Chrome 89 以上版本。 |
performance.now(),performance.timeOrigin
|
目前許多瀏覽器都支援這項功能,但解析度限制為 100 微秒以上。如果採用跨來源隔離,解析度可達 5 微秒以上。 |
跨來源隔離狀態也會防止修改 document.domain。(能夠變更 document.domain 可讓同網站文件進行通訊,因此被視為同源政策的漏洞。)
如要選擇啟用跨來源隔離狀態,您需要在主要文件中傳送下列 HTTP 標頭:
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
這些標頭會指示瀏覽器封鎖資源或 iframe 的載入作業,因為這些資源或 iframe 未選擇由跨來源文件載入,並防止跨來源視窗直接與您的文件互動。這也表示,跨來源載入的資源必須選擇加入。
您可以檢查 self.crossOriginIsolated,判斷網頁是否處於跨來源隔離狀態。
本文將說明如何使用這些新標題。我會在後續文章中提供更多背景資訊和相關內容。
部署 COOP 和 COEP,讓網站跨來源隔離
整合 COOP 和 COEP
1. 在頂層文件中設定 Cross-Origin-Opener-Policy: same-origin 標頭
在頂層文件中啟用 COOP: same-origin 後,具有相同來源的視窗,以及從該文件開啟的視窗,都會有不同的瀏覽內容群組,除非這些視窗的來源相同,且 COOP 設定也相同。因此,系統會強制隔離開啟的視窗,並停用兩個視窗之間的相互通訊。
瀏覽環境群組是一組可互相參照的視窗。舉例來說,頂層文件及其透過 <iframe> 嵌入的子項文件。如果網站 (https://a.example) 開啟彈出式視窗 (https://b.example),
開啟器視窗和彈出式視窗會共用相同的瀏覽環境,因此
可透過 DOM API (例如 window.opener) 存取彼此。

您可以透過開發人員工具,檢查視窗開啟器及其開啟的視窗是否位於不同的瀏覽內容群組。
2. 確認資源已啟用 CORP 或 CORS
請確認網頁中的所有資源都已載入 CORP 或 CORS HTTP 標頭。這是步驟四 (啟用 COEP) 的必要步驟。
請根據資源性質採取下列行動:
- 如果資源只應從相同來源載入,請設定
Cross-Origin-Resource-Policy: same-origin標頭。 - 如果資源預計只會從同一個網站載入,但會跨來源,請設定
Cross-Origin-Resource-Policy: same-site標頭。 - 如果資源是從您控管的跨來源載入,請盡可能設定
Cross-Origin-Resource-Policy: cross-origin標頭。 - 對於您無法控管的跨來源資源:
- 如果資源是透過 CORS 提供服務,請在載入 HTML 標記中使用
crossorigin屬性。例如<img src="***" crossorigin>。 - 請資源擁有者支援 CORS 或 CORP。
- 如果資源是透過 CORS 提供服務,請在載入 HTML 標記中使用
- 如果是 iframe,請按照上述原則設定
Cross-Origin-Resource-Policy: cross-origin(或same-site、same-origin,視情況而定)。 - 使用
WebWorker載入的指令碼必須從同源提供,因此您不需要 CORP 或 CORS 標頭。 - 如果文件或 Worker 是透過
COEP: require-corp提供服務,則載入的跨源子資源必須設定Cross-Origin-Resource-Policy: cross-origin標頭,才能選擇嵌入,且不得使用 CORS。舉例來說,這適用於<script>、importScripts、<link>、<video>、<iframe>等。
3. 使用 COEP Report-Only HTTP 標頭評估內嵌資源
全面啟用 COEP 之前,您可以先使用 Cross-Origin-Embedder-Policy-Report-Only 標頭進行模擬測試,檢查政策是否確實有效。您會收到報表,但內嵌內容不會遭到封鎖。
將這項設定遞迴套用至所有文件,包括頂層文件、iframe 和工作人員指令碼。如要瞭解 Report-Only HTTP 標頭,請參閱使用 Reporting API 觀察問題。
4. 啟用 COEP
確認一切運作正常,且所有資源都能順利載入後,請將 Cross-Origin-Embedder-Policy-Report-Only 標頭切換為 Cross-Origin-Embedder-Policy 標頭,並為所有文件 (包括透過 iframe 和 Worker 指令碼嵌入的文件) 設定相同值。
使用 self.crossOriginIsolated 判斷隔離是否成功
當網頁處於跨來源隔離狀態,且所有資源和視窗都隔離在同一個瀏覽環境群組中時,self.crossOriginIsolated 屬性會傳回 true。您可以使用這個 API 判斷是否已成功隔離瀏覽內容群組,並取得 performance.measureUserAgentSpecificMemory() 等強大功能的存取權。
使用 Chrome 開發人員工具偵錯
如果是顯示在畫面上的資源 (例如圖片),偵測 COEP 問題相當容易,因為系統會封鎖要求,且網頁會指出缺少圖片。不過,對於不一定會產生視覺影響的資源 (例如指令碼或樣式),COEP 問題可能不會受到注意。如要查看這些要求,請使用開發人員工具的「Network」面板。如果 COEP 有問題,您應該會在「狀態」欄中看到 (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)。
然後點選項目即可查看詳細資料。
您也可以透過「應用程式」面板判斷 iframe 和彈出式視窗的狀態。前往左側的「Frames」部分,然後展開「top」,即可查看資源結構的細目。
您可以檢查 iframe 的狀態,例如 SharedArrayBuffer 的可用性等。
您也可以查看彈出式視窗的狀態,例如是否為跨來源隔離。
使用 Reporting API 觀察問題
Reporting API 是另一種機制,可協助您偵測各種問題。您可以設定 Reporting API,指示使用者瀏覽器在 COEP 封鎖資源載入作業或 COOP 隔離彈出式視窗時傳送報告。自 69 版起,Chrome 就支援 Reporting API,可用於各種用途,包括 COEP 和 COOP。
如要瞭解如何設定 Reporting API,以及設定伺服器來接收報表,請參閱「使用 Reporting API」一文。
COEP 報表範例
如果跨來源資源遭到封鎖,COEP 報表的酬載範例如下:
[{
"age": 25101,
"body": {
"blocked-url": "https://third-party-test.glitch.me/check.svg?",
"blockedURL": "https://third-party-test.glitch.me/check.svg?",
"destination": "image",
"disposition": "enforce",
"type": "corp"
},
"type": "coep",
"url": "https://cross-origin-isolation.glitch.me/?coep=require-corp&coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36"
}]
COOP 報表範例
開啟隔離的彈出式視窗時,COOP 報告酬載的範例如下:
[{
"age": 7,
"body": {
"disposition": "enforce",
"effectivePolicy": "same-origin",
"nextResponseURL": "https://third-party-test.glitch.me/popup?report-only&coop=same-origin&",
"type": "navigation-from-response"
},
"type": "coop",
"url": "https://cross-origin-isolation.glitch.me/coop?coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]
當不同的瀏覽環境群組嘗試互相存取時 (僅限「僅回報」模式),COOP 也會傳送報告。舉例來說,嘗試 postMessage() 時的報表會如下所示:
[{
"age": 51785,
"body": {
"columnNumber": 18,
"disposition": "reporting",
"effectivePolicy": "same-origin",
"lineNumber": 83,
"property": "postMessage",
"sourceFile": "https://cross-origin-isolation.glitch.me/popup.js",
"type": "access-from-coop-page-to-openee"
},
"type": "coop",
"url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
},
{
"age": 51785,
"body": {
"disposition": "reporting",
"effectivePolicy": "same-origin",
"property": "postMessage",
"type": "access-to-coop-page-from-openee"
},
"type": "coop",
"url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]
結論
使用 COOP 和 COEP HTTP 標頭的組合,將網頁加入特殊的跨來源隔離狀態。您可以檢查
self.crossOriginIsolated,判斷網頁是否處於跨來源隔離狀態。
如果這個跨來源隔離狀態推出新功能,或開發人員工具在 COOP 和 COEP 方面有進一步改善,我們會持續更新這篇文章。