相關網站集:開發人員指南

相關網站集合 (RWS) 是一種網路平台機制,可協助瀏覽器瞭解網域集合之間的關係。瀏覽器可根據這項資訊做出重要決策,啟用特定網站功能 (例如是否允許存取跨網站 Cookie),並向使用者顯示這項資訊。

許多網站會使用多個網域,提供單一使用者體驗。 機構可能想為多個用途維護不同的頂層網域,例如國家/地區專屬網域,或是用於代管圖片或影片的服務網域。相關網站集合可讓網站跨網域共用資料,並提供特定控制項。

概括來說,相關網站集是一組網域,其中包含一個「集合主要」網域,以及可能有多個「集合成員」網域。

在下列範例中,primary 列出主網域,associatedSites 則列出符合「相關子集」規定的網域。

{
  "primary": "https://primary.com",
  "associatedSites": ["https://associate1.com", "https://associate2.com", "https://associate3.com"]
}

相關網站組合會列在 GitHub 上代管的公開 JSON 檔案中。這是所有核准套件的標準來源。瀏覽器會使用這個檔案,判斷網站是否屬於同一個相關網站集合。

只有具備網域管理控制權的使用者,才能使用該網域建立一組設定。提交者必須聲明每個「集合成員」與「集合主要項目」之間的關係。設定成員可包含各種不同網域類型,且必須是根據用途的子集

如果應用程式需要存取相同相關網站集合中各網站的跨網站 Cookie (也稱為第三方 Cookie),可以使用 Storage Access API (SAA)requestStorageAccessFor API 要求存取這些 Cookie。瀏覽器可能會根據每個網站所屬的子集,以不同方式處理要求。

如要進一步瞭解提交套裝組合的程序和規定,請參閱提交指南。提交的檔案集會經過各種技術檢查,以驗證提交內容。

如果機構需要在不同的頂層網站之間共用身分,相關網站集合就是合適的解決方案。

相關網站集合的用途包括:

  • 自訂國家/地區。利用本地化網站,同時依賴共用基礎架構 (example.co.uk 可能依賴 example.ca 代管的服務)。
  • 整合服務網域。利用使用者從未直接互動的服務網域,但在同一機構的網站提供服務 (例如 example-cdn.com)。
  • 使用者內容分離:存取不同網域的資料,基於安全考量,這些網域會將使用者上傳的內容與其他網站內容分開,同時允許沙箱網域存取驗證 (和其他) Cookie。如果您提供的是非使用者的上傳內容,也可以按照最佳做法,安全地將這類內容代管在同一個網域中。
    • 嵌入經過驗證的內容。支援從相關聯的資源嵌入內容 (影片、文件或資源僅限於登入頂層網站的使用者)。
  • 登入。支援在相關聯的資源之間登入。在某些情況下,FedCM API 也可能適用。
  • Analytics。在聯盟資源中部署使用者歷程分析和評估,以提升服務品質。

相關網站集合整合詳細資料

儲存空間存取權 API

Browser Support

  • Chrome: 119.
  • Edge: 85.
  • Firefox: 65.
  • Safari: 11.1.

Source

Storage Access API (SAA) 可讓嵌入的跨來源內容存取儲存空間,這類內容通常只能在第一方環境中存取儲存空間。

內嵌資源可以使用 SAA 方法,檢查目前是否具有儲存空間存取權,並向使用者代理程式要求存取權。

如果系統封鎖第三方 Cookie,但啟用相關網站集合 (RWS),Chrome 會在 RWS 內自動授予權限,否則會向使用者顯示提示。(「RWS 內文」是指內嵌網站和頂層網站位於相同 RWS 的背景資訊,例如 iframe)。

檢查及要求存取儲存空間

如要檢查目前是否能存取儲存空間,內嵌網站可以使用 Document.hasStorageAccess() 方法。

這個方法會傳回 Promise,並以布林值解析,指出文件是否已可存取 Cookie。如果 iframe 與頂層影格同源,這個 Promise 也會傳回 true。

如要在跨網站環境中要求存取 Cookie,嵌入的網站可以使用 Document.requestStorageAccess() (rSA)。

requestStorageAccess() API 應從 iframe 內呼叫。 該 iframe 必須剛收到使用者互動 (所有瀏覽器都要求的使用者手勢),但 Chrome 還要求使用者在過去 30 天內,必須曾造訪擁有該 iframe 的網站,並與該網站互動 (以頂層文件形式,而非在 iframe 中)。

requestStorageAccess() 會傳回 Promise,如果系統授予儲存空間存取權,就會解析該 Promise。如果存取權因任何原因遭到拒絕,系統會拒絕 Promise 並說明原因。

Chrome 中的 requestStorageAccessFor

Browser Support

  • Chrome: 119.
  • Edge: 119.
  • Firefox: not supported.
  • Safari: not supported.

Source

Storage Access API 只允許嵌入網站從已與使用者互動的 <iframe> 元素內要求存取儲存空間。

如果頂層網站使用需要 Cookie 的跨網站圖片或指令碼標記,採用 Storage Access API 時就會遇到困難。

為解決這個問題,Chrome 實作了一種機制,讓頂層網站能代表特定來源,透過 Document.requestStorageAccessFor() (rSAFor) 要求儲存空間存取權。

 document.requestStorageAccessFor('https://target.site')

requestStorageAccessFor() API 應由頂層文件呼叫。該文件也必須剛與使用者互動。但與 requestStorageAccess() 不同的是,Chrome 不會檢查使用者在過去 30 天內是否與頂層文件互動,因為使用者已在網頁上。

檢查儲存空間存取權

部分瀏覽器功能 (例如攝影機或地理位置) 的存取權取決於使用者授予的權限。Permissions API 可讓您檢查存取 API 的權限狀態,包括是否已授予、拒絕,或需要某種形式的使用者互動,例如點選提示或與網頁互動。

您可以使用 navigator.permissions.query() 查詢權限狀態。

如要檢查目前環境的儲存空間存取權,您需要傳遞 'storage-access' 字串:

navigator.permissions.query({name: 'storage-access'})

如要檢查特定來源的儲存空間存取權限,請傳遞 'top-level-storage-access' 字串:

navigator.permissions.query({name: 'top-level-storage-access', requestedOrigin: 'https://target.site'})

請注意,為保護嵌入來源的完整性,這項檢查只會使用 document.requestStorageAccessFor 檢查頂層文件授予的權限。

視權限是否可自動授予或需要使用者手勢而定,系統會傳回 promptgranted

每影格模型

rSA 授權適用於每個影格。rSA 和 rSAFor 授權視為個別權限。

每個新影格都必須個別要求儲存空間存取權,系統會自動授予存取權。只有第一個要求需要使用者手勢,iframe 啟動的任何後續要求 (例如導覽或子資源) 都不必等待使用者手勢,因為初始要求會為瀏覽工作階段授予權限。

重新整理、重新載入或以其他方式重新建立 iframe 時,必須再次要求存取權。

Cookie 必須同時指定 SameSite=NoneSecure 屬性,因為只有 rSA 才能提供存取權,讓 Cookie 用於已標記為跨網站環境的 Cookie

含有 SameSite=LaxSameSite=Strict 或沒有 SameSite 屬性的 Cookie 僅供第一方使用,絕不會在跨網站環境中分享,無論是否為 RSA 皆然。

安全性

對於 rSAFor,子資源要求需要跨源資源共享 (CORS) 標頭或資源上的 crossorigin 屬性,確保明確選擇加入。

導入範例

從內嵌的跨來源 iframe 要求存取儲存空間

圖表:頂層網站上嵌入的網站
在其他網站上嵌入 requestStorageAccess()

確認你是否具備儲存空間存取權

如要檢查是否已具備儲存空間存取權,請使用 document.hasStorageAccess()

如果 Promise 解析為 true,您就能在跨網站環境中存取儲存空間。 如果解析結果為 false,您需要要求儲存空間存取權。

document.hasStorageAccess().then((hasAccess) => {
    if (hasAccess) {
      // You can access storage in this context
    } else {
      // You have to request storage access
    }
});

要求儲存空間存取權

如要要求儲存空間存取權,請先查看儲存空間存取權限navigator.permissions.query({name: 'storage-access'}),確認是否需要使用者手勢,或是否可自動授予。

如果權限為 granted,您可以呼叫 document.requestStorageAccess(),且應該不需要使用者手勢就能成功。

如果權限狀態為 prompt,您需要在使用者手勢 (例如點選按鈕) 後啟動 document.requestStorageAccess() 呼叫。

範例:

navigator.permissions.query({name: 'storage-access'}).then(res => {
  if (res.state === 'granted') {
    // Permission has already been granted
    // You can request storage access without any user gesture
    rSA();
  } else if (res.state === 'prompt') {
    // Requesting storage access requires user gesture
    // For example, clicking a button
    const btn = document.createElement("button");
    btn.textContent = "Grant access";
    btn.addEventListener('click', () => {
      // Request storage access
      rSA();
    });
    document.body.appendChild(btn);
  }
});

function rSA() {
  if ('requestStorageAccess' in document) {
    document.requestStorageAccess().then(
      (res) => {
        // Use storage access
      },
      (err) => {
        // Handle errors
      }
    );
  }
}

框架、導覽或子資源後續提出的要求,將自動獲得存取跨網站 Cookie 的權限。hasStorageAccess() 會傳回 true,且來自相同相關網站組合的跨網站 Cookie 會在這些要求中傳送,不需任何額外的 JavaScript 呼叫。

頂層網站代表跨來源網站要求 Cookie 存取權

圖表:顯示在頂層網站上使用 requestStorageAccessFor(),而非在嵌入內容中使用
在不同來源的頂層網站上使用 requestStorageAccessFor()

頂層網站可以使用 requestStorageAccessFor(),代表特定來源要求儲存空間存取權。

hasStorageAccess() 只會檢查呼叫該函式的網站是否具有儲存空間存取權,因此頂層網站可以檢查其他來源的權限。

如要瞭解系統是否會提示使用者,或是否已將儲存空間存取權授予指定來源,請呼叫 navigator.permissions.query({name: 'top-level-storage-access', requestedOrigin: 'https://target.site'})

如果權限為 granted,您可以呼叫 document.requestStorageAccessFor('https://target.site')。且不需使用者手勢即可成功。

如果權限為 prompt,您需要將 document.requestStorageAccessFor('https://target.site') 呼叫掛鉤在使用者手勢 (例如點按按鈕) 後方。

範例:

navigator.permissions.query({name:'top-level-storage-access',requestedOrigin: 'https://target.site'}).then(res => {
  if (res.state === 'granted') {
    // Permission has already been granted
    // You can request storage access without any user gesture
    rSAFor();
  } else if (res.state === 'prompt') {
    // Requesting storage access requires user gesture
    // For example, clicking a button
    const btn = document.createElement("button");
    btn.textContent = "Grant access";
    btn.addEventListener('click', () => {
      // Request storage access
      rSAFor();
    });
    document.body.appendChild(btn);
  }
});

function rSAFor() {
  if ('requestStorageAccessFor' in document) {
    document.requestStorageAccessFor().then(
      (res) => {
        // Use storage access
      },
      (err) => {
        // Handle errors
      }
    );
  }
}

成功呼叫 requestStorageAccessFor() 後,如果跨網站要求包含 CORS 或 crossorigin 屬性,就會納入 Cookie,因此網站可能需要等待,再觸發要求。

要求必須使用 credentials: 'include' 選項,且資源必須包含 crossorigin="use-credentials" 屬性。

function checkCookie() {
    fetch('https://related-website-sets.glitch.me/getcookies.json', {
        method: 'GET',
        credentials: 'include'
      })
      .then((response) => response.json())
      .then((json) => {
      // Do something
      });
  }

如何在本機測試

必要條件

如要在本機測試相關網站組合,請使用從命令列啟動的 Chrome 119 以上版本,並啟用 test-third-party-cookie-phaseout Chrome 旗標

啟用 Chrome 旗標

如要啟用必要的 Chrome 旗標,請前往網址列並將旗標變更為 chrome://flags#test-third-party-cookie-phaseoutEnabled。變更標記後,請務必重新啟動瀏覽器。

啟動 Chrome,並使用本機相關網站集合

如要啟動 Chrome 並使用本機宣告的相關網站組合,請建立包含組合成員網址的 JSON 物件,並將該物件傳遞至 --use-related-website-set

進一步瞭解如何使用標記執行 Chromium

--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/

範例

如要在本機啟用相關網站組合,您需要在 chrome://flags 中啟用 test-third-party-cookie-phaseout,並從指令列啟動 Chrome,同時使用 --use-related-website-set 旗標和 JSON 物件,其中包含組合成員的網址。

--use-related-website-set="{\"primary\": \"https://related-website-sets.glitch.me\", \"associatedSites\": [\"https://rws-member-1.glitch.me\"]}" \
https://related-website-sets.glitch.me/

確認您有權存取跨網站 Cookie

從測試中的網站呼叫 API (rSA 或 rSAFor),並驗證跨網站 Cookie 的存取權。

相關網站集合提交程序

請按照下列步驟宣告網域之間的關係,並指定網域所屬的子集。

1. 找出 RWS

找出相關網域,包括將成為相關網站集一部分的主要網站成員網站。並找出每個集合成員所屬的子集類型

2. 建立 RWS 提交內容

建立 GitHub 存放區的本機副本 (複製或建立分支)。在新分支中變更related_website_sets.JSON 檔案,以反映您的組合。如要確保集合的 JSON 格式和結構正確無誤,可以使用 JSON 產生器工具

3. 確認 RWS 符合技術規定

確保符合集合建立規定集合驗證規定

4. 在本機測試 RWS

建立提取要求 (PR) 提交設定前,請先在本機測試提交內容,確保通過所有必要檢查。

5. 提交 RWS

如要提交相關網站集合,請建立 PR,並提交至 Chrome 存放標準相關網站集合清單的 related_website_sets.JSON 檔案。(您必須擁有 GitHub 帳戶才能建立 PR,且必須先簽署《貢獻者授權協議 (CLA)》,才能為清單貢獻內容)。

建立 PR 後,系統會完成一系列檢查,確保符合步驟 3 的規定,例如確認您已簽署 CLA,且 .well-known 檔案有效。

如果成功,PR 會顯示檢查已通過。獲准的 PR 會每週一次 (美國東部時間週二中午 12 點) 手動分批合併至標準相關網站集清單。如果任何檢查失敗,系統會在 GitHub 上通知提交者 PR 失敗。提交者可以修正錯誤並更新 PR,請注意以下事項:

  • 如果 PR 失敗,錯誤訊息會提供額外資訊,說明提交失敗的原因。(範例)。
  • 所有與提交設定相關的技術檢查都會在 GitHub 上進行,因此,您可以在 GitHub 上查看因技術檢查而導致的所有提交失敗。

企業政策

Chrome 提供兩項政策,滿足企業使用者的需求:

  • 如果系統無法與相關網站集整合,可以透過 RelatedWebsiteSetsEnabled 政策,在所有企業版 Chrome 執行個體中停用相關網站集功能。
    • 部分企業系統有僅供內部使用的網站 (例如內部網路),其可註冊網域與相關網站集合中的網域不同。如果他們需要將這些網站視為相關網站集的一部分,但不想公開這些網站 (因為網域可能屬於機密),可以透過RelatedWebsiteSetsOverrides政策擴增或覆寫公開的相關網站集清單。

Chrome 會以兩種方式之一,解決公開和企業集之間的任何交集,具體取決於是否指定 replacementsadditions

舉例來說,如果是公開設定 {primary: A, associated: [B, C]}

replacements 組: {primary: C, associated: [D, E]}
企業集會吸收一般網站,形成新的集合。
產生的集合: {primary: A, associated: [B]}
{primary: C, associated: [D, E]}
additions 組: {primary: C, associated: [D, E]}
公開和企業版設定檔會合併。
產生的集合: {primary: C, associated: [A, B, D, E]}

排解相關網站集問題

「使用者提示」和「使用者手勢」

「使用者提示」和「使用者手勢」是不同的概念。如果網站位於相同的相關網站組合中,Chrome 不會向使用者顯示權限提示,但仍會要求使用者與網頁互動。授予權限前,Chrome 會要求使用者手勢,也稱為「使用者互動」或「使用者啟用」。這是因為根據網頁平台設計原則,在相關網站集合以外的環境 (即 requestStorageAccess()) 使用 Storage Access API 時,也需要使用者手勢。

存取其他網站的 Cookie 或儲存空間

相關網站集合不會合併不同網站的儲存空間,只會允許更輕鬆 (無提示) 的 requestStorageAccess() 呼叫。相關網站集合只會降低使用 Storage Access API 時的使用者摩擦,但不會規定存取權還原後該怎麼做。如果 A 和 B 是同一個相關網站集合中的不同網站,且 A 嵌入 B,B 即可呼叫 requestStorageAccess() 並存取第一方儲存空間,不必提示使用者。相關網站集不會執行任何跨網站通訊。舉例來說,設定相關網站集合不會導致屬於 B 的 Cookie 開始傳送至 A。如要分享這類資料,您必須自行分享,例如從 B iframe 傳送 window.postMessage 至 A 框架。

相關網站集合不允許在未叫用任何 API 的情況下,隱含存取未分割的 Cookie。在集合中,系統預設不會提供跨網站 Cookie;相關網站集合只允許集合中的網站略過 Storage Access API 權限提示。 如果 iframe 想存取 Cookie,就必須呼叫 document.requestStorageAccess(),頂層網頁則可呼叫 document.requestStorageAccessFor()

提供意見

在 GitHub 上提交一組測試案例,並使用 Storage Access API 和 requestStorageAccessFor API,有助於分享您在過程中遇到的任何問題。

如要加入相關網站集合的討論: