使用 COOP 和 COEP 建立網站 "跨來源隔離

使用 COOP 和 COEP 設定跨來源隔離環境,並啟用強大的功能,例如 SharedArrayBufferperformance.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 日:移除 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 推出。

部分網頁 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。
  • 如果是 iframe,請按照上述原則設定 Cross-Origin-Resource-Policy: cross-origin (或 same-sitesame-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)

「網路」面板「狀態」欄中的 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,以及設定伺服器來接收報表,請參閱「使用 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 方面有進一步改善,我們會持續更新這篇文章。

資源