Storage Access API
儲存訪問API提供了一種方式,允許以第三方上下文(即嵌入在 中)載入的跨站點內容訪問通常只能在第一方上下文(即直接載入到瀏覽器標籤頁中)才能訪問的第三方Cookie和未分割槽狀態。
儲存訪問API與預設阻止訪問第三方Cookie和未分割槽狀態以提高隱私(例如,防止跟蹤)的使用者代理相關。即使在這些預設限制存在的情況下,我們仍然希望啟用第三方Cookie和未分割槽狀態的合法用途。示例包括與聯邦身份提供商 (IdP) 的單點登入 (SSO),或者在不同站點之間持久化使用者詳細資訊(如位置資料或檢視偏好)。
該API提供了方法,允許嵌入式資源檢查它們當前是否具有第三方Cookie訪問許可權,如果否,則向用戶代理請求訪問許可權。
概念與用法
瀏覽器實現了多種儲存訪問功能和策略,限制了對第三方Cookie和未分割槽狀態的訪問。這些功能從為每個頂級源下的嵌入式資源提供唯一的Cookie儲存空間(分割槽Cookie)到在第三方上下文中載入資源時完全阻止Cookie訪問。
第三方Cookie和未分割槽狀態阻止功能和策略的語義因瀏覽器而異,但核心功能相似。嵌入在第三方上下文中的跨站點資源無法訪問它們在第一方上下文中可以訪問的相同狀態。這樣做是出於善意——瀏覽器供應商希望採取措施更好地保護使用者的隱私和安全。例如,減少使用者在不同站點上的活動被跟蹤的可能性,並降低受到跨站請求偽造(CSRF)等漏洞攻擊的風險。
然而,嵌入式跨站點內容訪問第三方Cookie和未分割槽狀態存在合法用途,而上述功能和策略已知會破壞這些用途。假設您有一系列提供不同產品的網站——heads-example.com、shoulders-example.com、knees-example.com和toes-example.com。
或者,您可能會出於本地化目的將內容或服務分離到不同的國家/地區域——example.com、example.ua、example.br等——或以其他方式進行分離。
您可能擁有伴隨的實用工具站點,其中包含嵌入在所有其他站點中的元件,例如,用於提供SSO(sso-example.com)或通用個性化服務(services-example.com)。這些實用工具站點將希望透過Cookie與它們嵌入的站點共享其狀態。它們無法共享第一方Cookie,因為它們位於不同的域中,而第三方Cookie在阻止它們的瀏覽器中將不再起作用。
在這種情況下,站點所有者通常會鼓勵使用者將他們的站點新增為例外,或完全停用第三方Cookie阻止策略。希望繼續與其內容互動的使用者必須顯著放寬對所有嵌入式源以及可能所有網站載入資源的阻止策略。
儲存訪問API旨在解決此問題;嵌入式跨站點內容可以透過 Document.requestStorageAccess() 方法逐幀請求對第三方Cookie和未分割槽狀態的無限制訪問。它還可以透過 Document.hasStorageAccess() 方法檢查是否已擁有訪問許可權。
未分割槽與分割槽Cookie
值得注意的是,儲存訪問API僅需要提供對“未分割槽”第三方Cookie的訪問。這意味著自早期Web以來以傳統方式儲存的Cookie——所有在同一站點上設定的Cookie都儲存在同一個Cookie罐中。這與“分割槽”Cookie形成對比,後者為每個頂級站點下的嵌入式資源提供唯一的Cookie儲存空間,從而使得透過這些Cookie跨站點跟蹤使用者成為不可能。
瀏覽器具有各種機制來分割槽第三方Cookie訪問,例如 Firefox Total Cookie Protection 和 具有獨立分割槽狀態的Cookie(CHIPS)。
當我們在儲存訪問API的上下文中談論第三方Cookie時,我們隱含地指的是“未分割槽”第三方Cookie。
工作原理
合法需要第三方Cookie或未分割槽狀態訪問的嵌入式內容可以使用儲存訪問API請求訪問,具體如下:
- 它可以呼叫
Document.hasStorageAccess()方法來檢查它是否已經擁有所需的訪問許可權。 - 如果否,它可以透過
Document.requestStorageAccess()方法請求訪問。 - 根據瀏覽器的不同,使用者會被以略微不同的方式詢問是否授予請求嵌入的訪問許可權。
- Safari 會向所有之前未獲得儲存訪問許可權的嵌入式內容顯示提示。
- Firefox 僅在某個源在超過閾值數量的站點上請求儲存訪問後才會提示使用者。
- Chrome 會向所有之前未獲得儲存訪問許可權的嵌入式內容顯示提示。但是,如果嵌入式內容和嵌入站點屬於同一個 相關網站集,它將自動授予訪問許可權並跳過提示。
- 訪問的授予或拒絕基於內容是否滿足所有安全要求——有關一般要求,請參閱安全措施;有關某些瀏覽器特定的安全要求,請參閱瀏覽器特定差異。
requestStorageAccess()基於 Promise 的特性允許您執行程式碼來處理成功和失敗的情況。- 現代規範行為規定訪問許可權是“逐幀”授予的——每個獨立的內容嵌入預設都會阻止其第三方 Cookie 訪問,並且需要呼叫
requestStorageAccess()才能選擇啟用訪問。如果某個內容嵌入已獲得訪問許可權,並且同站嵌入隨後呼叫requestStorageAccess(),它們的 Promise 將自動履行。但它們仍然需要選擇啟用。 - “預設阻止”行為的唯一例外是當內容嵌入成功呼叫
requestStorageAccess()後,然後執行同源導航(例如重新載入自身)。在這種情況下,儲存訪問許可權會從之前的導航中繼承。 - 在舊的規範版本中,訪問許可權是“逐頁”的(Safari 是目前唯一仍在使用此模型的瀏覽器)。當一個嵌入透過
requestStorageAccess()獲得第三方 Cookie 訪問許可權時,所有其他同站嵌入都會自動獲得訪問許可權。從安全形度來看,這不是理想的行為——例如,如果shop.example.com嵌入了locator.users.com以允許使用者在購物時使用他們的位置資訊,並且locator.users.com呼叫了requestStorageAccess(),那麼shop.example.com及其嵌入的任何其他站點都將能夠訪問其 Cookie,但也會訪問來自private.users.com的 Cookie,而後者並非旨在被嵌入。閱讀有關此更改背後的動機的更多資訊。
- 現代規範行為規定訪問許可權是“逐幀”授予的——每個獨立的內容嵌入預設都會阻止其第三方 Cookie 訪問,並且需要呼叫
- 一旦授予訪問許可權,瀏覽器中會儲存一個許可權金鑰,其結構為
<頂級站點, 嵌入站點>。例如,如果嵌入站點是embedder.com,嵌入內容是locator.example.com,則金鑰將是。然後,同站嵌入(docs.example.com、profile.example.com等)將能夠呼叫requestStorageAccess(),並且Promise將自動實現,如前所述。- 舊的規範版本使用了更具體的許可權金鑰結構
<頂級站點, 嵌入源>,這意味著同站、跨源嵌入不匹配許可權金鑰,必須單獨經歷整個過程。
- 舊的規範版本使用了更具體的許可權金鑰結構
注意: 在頂級站點其 Cookie 被分割槽的情況下,儲存訪問API不是必需的,因為預設共享 Cookie 沒有隱私風險。
安全措施
有幾個不同的安全措施可能導致 Document.requestStorageAccess() 呼叫失敗。如果您在嘗試使請求正常工作時遇到問題,請檢查以下列表:
-
該呼叫必須與使用者手勢(瞬態啟用)相關聯,例如輕觸或點選。這可以防止頁面上的嵌入內容用過多的訪問請求來騷擾瀏覽器或使用者。請注意,在以下情況下不需要這樣做:
- 已授予使用 API 的許可權,例如透過另一個同站資源呼叫
requestStorageAccess()。 - 呼叫方是頂級文件或與頂級文件同站。在這種情況下,可能根本不需要呼叫
requestStorageAccess()。
- 已授予使用 API 的許可權,例如透過另一個同站資源呼叫
-
文件和頂級文件的源不能為
null。 -
從未作為第一方互動過的源沒有第一方儲存的概念。從使用者的角度來看,他們與該源只有第三方關係。如果瀏覽器檢測到使用者最近沒有在第一方上下文中與嵌入內容互動(在 Firefox 中,“最近”指30天內),則訪問請求將自動被拒絕。
-
文件的視窗必須是一個安全上下文。
-
由於安全原因,預設情況下,沙盒化
無法獲得儲存訪問許可權。因此,API 還添加了allow-storage-access-by-user-activation沙盒令牌。嵌入網站需要新增此令牌,以及allow-scripts和allow-same-origin,以允許執行指令碼來呼叫 API 並在可以擁有 cookie/狀態的源中執行它,才能使儲存訪問請求成功。html<iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin"> … </iframe> -
此功能的使用可能會被伺服器上設定的
storage-access許可權策略阻止。
注意: 文件可能還需要透過額外的瀏覽器特定檢查。例如:允許列表、阻止列表、裝置端分類、使用者設定、反點選劫持啟發式方法,或提示使用者明確許可。
瀏覽器特定差異
儘管 API 介面相同,但由於儲存訪問策略的差異,使用儲存訪問 API 的網站應預期在不同瀏覽器之間獲得的第三方 Cookie 訪問級別和範圍會有所不同。
Chrome
- Cookie 必須明確設定
SameSite=None,因為 Chrome 的預設值為SameSite=Lax(Firefox 和 Safari 的預設值為SameSite=None)。 - Cookie 必須設定
Secure屬性。 - 儲存訪問許可權會在瀏覽器使用30天且沒有使用者互動後逐步失效。與嵌入內容的互動會將此限制再延長30天。當呼叫
Document.requestStorageAccessFor()時不會發生這種情況,因為使用者已經在頁面上。
Firefox
- 如果嵌入源
tracker.example已經獲得了頂級源foo.example上的第三方 Cookie 訪問許可權,並且使用者在不到30天內再次訪問了foo.example嵌入tracker.example頁面的頁面,那麼嵌入源在載入時將立即獲得第三方 Cookie 訪問許可權。 - 儲存訪問授權將在30個日曆日後失效。
Firefox 新儲存訪問策略(用於阻止跟蹤 Cookie)的文件包含對儲存訪問授權範圍的詳細描述。
Safari
- 儲存訪問許可權會在瀏覽器使用30天且沒有使用者互動後逐步失效。成功使用儲存訪問API會重置此計數器。
示例
- 有關包含程式碼示例的實現指南,請參閱使用儲存訪問API。
API方法
Document.hasStorageAccess()-
返回一個 Promise,該 Promise 解析為一個布林值,指示文件是否具有對第三方 Cookie 的訪問許可權。
-
Document.hasStorageAccess()的新名稱。 Document.requestStorageAccess()-
允許在第三方上下文中(即嵌入在
中)載入的內容請求訪問第三方 Cookie 和未分割槽狀態;返回一個 Promise,如果授予訪問許可權則解析,如果拒絕訪問許可權則拒絕。 Document.requestStorageAccessFor()實驗性-
儲存訪問 API 的一個提議擴充套件,允許頂級站點代表來自同一相關網站集中的另一個站點的嵌入內容請求第三方 Cookie 訪問許可權。返回一個 Promise,如果授予訪問許可權則解析,如果拒絕訪問許可權則拒絕。
注意: 使用者互動會傳播到這些方法返回的 Promise,允許呼叫者執行需要使用者互動的操作,而無需第二次點選。例如,呼叫者可以從已解析的 Promise 中開啟一個彈出視窗,而不會觸發 Firefox 的彈出視窗阻止程式。
對其他API的補充
Permissions.query(),"storage-access"功能名稱-
在支援的瀏覽器中,這可以查詢是否通常已授予第三方 Cookie 訪問許可權,即授予另一個同站嵌入。如果是這樣,您可以在沒有使用者互動的情況下呼叫
requestStorageAccess(),並且 Promise 將自動解決。 Permissions.query(),"top-level-storage-access"功能名稱 實驗性-
一個單獨的功能名稱,用於查詢是否已透過
requestStorageAccessFor()授予訪問第三方 Cookie 的許可權。如果是這樣,您無需再次呼叫requestStorageAccessFor()。
規範
| 規範 |
|---|
| Storage Access API |
| 將儲存訪問API(SAA)擴充套件到非Cookie儲存 |
瀏覽器相容性
api.Document.hasStorageAccess
載入中…
api.Document.hasUnpartitionedCookieAccess
載入中…
api.Document.requestStorageAccess
載入中…
api.Document.requestStorageAccessFor
載入中…
api.Permissions.permission_storage-access
載入中…
另見
- 使用 Storage Access API
- Storage Access API 介紹 (WebKit 部落格)