使用 COOP 和 COEP 將網站設為「已跨來源隔離」

使用 COOP 和 COEP 設定已跨來源隔離環境,並啟用 SharedArrayBufferperformance.measureUserAgentSpecificMemory() 和高解析度計時器等強大功能,提升精確度。

發布日期:2020 年 4 月 13 日,上次更新時間:2022 年 6 月 21 日

本文說明如何使用這些 COOP 和 COEP。如要進一步瞭解這項措施的重要性,請參閱「使用 COOP 和 COEP 將網站設為「跨來源隔離」」。

部分網頁 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,判斷網頁是否處於已跨來源隔離狀態。

詞彙解釋

這份文件使用許多名稱相似且縮寫的術語。為求清楚明瞭,我們整理了迷你詞彙表:

讓網站已跨來源隔離

1. 在頂層文件中設定 Cross-Origin-Opener-Policy: same-origin

在頂層文件中啟用 COOP: same-origin 後,具有相同來源的視窗和從該文件開啟的視窗會屬於不同的瀏覽內容群組,除非這些視窗的來源相同,且 COOP 設定也相同。因此,系統會強制隔離開啟的視窗,並停用兩個視窗之間的相互通訊。

瀏覽環境群組是一組可以互相參照的視窗。舉例來說,頂層文件及其以 <iframe> 嵌入的子項文件。如果網站 (https://a.example) 開啟對話方塊視窗 (https://b.example),開啟器視窗和對話方塊視窗會共用相同的瀏覽環境,因此可透過 window.opener 等 DOM API 互相存取。

插圖:代表瀏覽內容群組,使用者與網頁元素互動。

您可以透過開發人員工具,檢查視窗開啟者及其開啟的視窗是否位於不同的瀏覽環境群組。

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。
  • 如果是 iframe,請遵循相同原則並設定 Cross-Origin-Resource-Policy: cross-origin (或 same-sitesame-origin,視情況而定)。
  • 使用 WebWorker 載入的指令碼必須從同源放送,因此您不需要 CORP 或 CORS 標頭。
  • 如果文件或工作人員是透過 COEP: require-corp 提供服務,則載入的跨源子資源必須設定 Cross-Origin-Resource-Policy: cross-origin 標頭,才能選擇嵌入,且不得使用 CORS。例如:<script>importScripts<link><video><iframe> 等。

iframe 中的隔離

如要對 iframe 內嵌的文件啟用跨來源隔離功能,請對 <iframe> 標記套用 allow="cross-origin-isolated" 權限政策,並符合下列條件。整個文件鏈 (包括父框架和子框架) 也必須跨來源隔離。

3. 使用 COEP Report-Only HTTP 標頭評估內嵌資源

全面啟用 COEP 之前,您可以先使用 Cross-Origin-Embedder-Policy-Report-Only 標頭進行模擬測試,檢查政策是否確實有效。您會收到報表,但不會封鎖嵌入式內容。

將這項設定遞迴套用至所有文件,包括頂層文件、iframe 和工作人員指令碼。如要瞭解 Report-Only HTTP 標頭,請參閱「使用 Reporting API 觀察問題」。

4. 啟用 COEP

您必須先確保資源已啟用 CORP 或 CORS,才能執行這個步驟。

確認一切運作正常,且所有資源都能順利載入後,請將 Cross-Origin-Embedder-Policy-Report-Only 標頭切換為 Cross-Origin-Embedder-Policy 標頭,並為所有文件 (包括以 iframe 和工作人員指令碼嵌入的文件) 設定相同值。

判斷隔離是否成功

當網頁處於已跨來源隔離狀態,且所有資源和視窗都隔離在同一個瀏覽環境群組中時,self.crossOriginIsolated 屬性會傳回 true。您可以使用這個 API 判斷是否已成功隔離瀏覽內容群組,並取得 performance.measureUserAgentSpecificMemory() 等功能的存取權。

偵錯

您可能會遇到 COOP 和 COEP 問題。您可以使用瀏覽器開發人員工具或 Reporting API 進行偵錯。

使用 Chrome 開發人員工具進行偵錯

如果是圖片等顯示在螢幕上的資源,偵測 COEP 問題相當容易,因為要求遭到封鎖,且網頁應會指出缺少圖片。不過,對於不一定會產生視覺影響的資源 (例如指令碼或樣式),COEP 問題可能會遭到忽略。如要查看這些要求,請使用開發人員工具的「網路」面板。

如果 COEP 有問題,您應該會在「狀態」欄中看到 (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)

「網路」面板「狀態」欄中的 COEP 問題。

然後點選項目即可查看詳細資料。

在「網路」面板中點選網路資源後,「標頭」分頁會顯示 COEP 問題的詳細資料。

您也可以透過「應用程式」面板判斷 iframe 和對話方塊視窗的狀態。前往左側的「Frames」部分,然後展開「top」,即可查看資源結構的細目。

您可以檢查 iframe 的狀態,例如 SharedArrayBuffer 的可用性等。

Chrome 開發人員工具 iframe 檢查器。

您也可以查看對話方塊的狀態,例如是否為跨來源隔離。

Chrome 開發人員工具對話方塊檢查器

使用 Reporting API 觀察問題

Reporting API 是另一種機制,可協助您偵測各種問題。您可以設定 Reporting API,指示使用者瀏覽器在 COEP 封鎖資源載入或 COOP 隔離對話方塊時傳送報表。自 69 版起,Chrome 就支援 Reporting API,可用於各種用途,包括 COEP 和 COOP。

瞭解如何設定 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 進行改善,我們都會更新這篇文章

資源

文件更新

  • 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 日:移除 SharedArrayBufferperformance.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 推出。