Блокировка сторонних файлов cookie с помощью браузеров, пользовательских настроек и разделения хранилища представляет собой проблему для сайтов и служб, которые полагаются на файлы cookie и другие хранилища во встроенных контекстах для действий пользователя, таких как аутентификация. API доступа к хранилищу (SAA) позволяет этим вариантам использования продолжать работать, максимально ограничивая межсайтовое отслеживание.
Статус реализации
API доступа к хранилищу доступен во всех основных браузерах , но между браузерами существуют небольшие различия в реализации . Эти различия были подчеркнуты в соответствующих разделах этого поста.
Продолжается работа над решением всех оставшихся проблем с блокировкой перед стандартизацией API .
Что такое API доступа к хранилищу?
API доступа к хранилищу — это API JavaScript, который позволяет iframe запрашивать разрешения на доступ к хранилищу, если в противном случае доступ был бы запрещен настройками браузера. Встраивания со вариантами использования, которые зависят от загрузки межсайтовых ресурсов, могут использовать API для запроса разрешения на доступ у пользователя по мере необходимости.
Если запрос на хранение будет удовлетворен, iframe получит доступ к своим неразделенным файлам cookie и хранилищу, которые также доступны, когда пользователи посещают его как сайт верхнего уровня.
API доступа к хранилищу позволяет предоставлять определенные неразделенные файлы cookie и доступ к хранилищу с минимальной нагрузкой для конечного пользователя, в то же время предотвращая общий неразделенный доступ к файлам cookie и хранилищу, который часто используется для отслеживания пользователей.
Варианты использования
Некоторым сторонним встраиваниям требуется доступ к неразделенным файлам cookie или хранилищу, чтобы обеспечить удобство работы пользователя — то, что не будет доступно, если сторонние файлы cookie ограничены и включено разделение хранилища.
Варианты использования включают в себя:
- Встроенные виджеты комментариев, для которых требуются данные сеанса входа в систему.
- Кнопки «Мне нравится» в социальных сетях, для которых требуются данные сеанса входа в систему.
- Встроенные документы, для которых требуются данные сеанса входа в систему.
- Премиум-возможности, предоставляемые при встраивании видео (например, чтобы не показывать рекламу вошедшим в систему пользователям или знать предпочтения пользователя в отношении субтитров или ограничивать определенные типы видео).
- Встроенные платежные системы.
Многие из этих вариантов использования включают сохранение доступа для входа во встроенные iframe.
Когда использовать API доступа к хранилищу вместо других API
API доступа к хранилищу — это одна из альтернатив использованию неразделенных файлов cookie и хранилища, поэтому важно понимать, когда использовать этот API по сравнению с другими. Он предназначен для случаев использования, когда справедливы оба следующих условия:
- Пользователь будет взаимодействовать со встроенным контентом, то есть это не пассивный или скрытый iframe.
- Пользователь посетил встроенный источник в контексте верхнего уровня, то есть когда этот источник не встроен в другой сайт.
Существуют альтернативные API для различных случаев использования:
- Файлы cookie с независимым разделенным состоянием (CHIPS) позволяют разработчикам включать файлы cookie в «разделенное» хранилище с отдельной банкой файлов cookie для каждого сайта верхнего уровня. Например, сторонний виджет веб-чата может использовать установку файла cookie для сохранения информации о сеансе. Информация о сеансе сохраняется для каждого сайта, поэтому к файлу cookie, установленному виджетом, нет необходимости обращаться на других веб-сайтах, где он также встроен. API доступа к хранилищу полезен, когда встроенный сторонний виджет зависит от совместного использования одной и той же информации в разных источниках (например, для сведений о сеансе входа или предпочтений).
- Разделение хранилища — это способ межсайтовых iframe использовать существующие механизмы хранения JavaScript при разделении базового хранилища для каждого сайта. Это предотвращает доступ к встроенному хранилищу на одном веб-сайте с помощью той же вставки на других веб-сайтах.
- Наборы связанных веб-сайтов (RWS) — это способ для организации объявить взаимосвязи между сайтами, чтобы браузеры разрешали ограниченный доступ к неразделенным файлам cookie и хранилищу для определенных целей. Сайтам по-прежнему необходимо запрашивать доступ с помощью API доступа к хранилищу, но для сайтов в наборе доступ может быть предоставлен без запросов пользователя.
- Федеративное управление учетными данными (FedCM) — это подход к федеративным службам идентификации, обеспечивающий сохранение конфиденциальности. API доступа к хранилищу обеспечивает доступ к неразделенным файлам cookie и хранилищу после входа в систему. В некоторых случаях использования FedCM предоставляет альтернативное решение API доступа к хранилищу и может быть предпочтительнее, поскольку оно имеет более ориентированное на вход приглашение браузера. Однако внедрение FedCM обычно требует дополнительных изменений в вашем коде, например, для поддержки конечных точек HTTP.
- Также существуют API для защиты от мошенничества , рекламы и измерения , и API доступа к хранилищу не предназначен для решения этих проблем.
Используйте API доступа к хранилищу
API доступа к хранилищу имеет два метода на основе обещаний:
-
Document.hasStorageAccess()
(также доступен под новым именемDocument.hasUnpartitionedCookieAccess()
начиная с Chrome 125) -
Document.requestStorageAccess()
Он также интегрируется с API разрешений . Это позволяет вам проверить статус разрешения доступа к хранилищу в стороннем контексте, который указывает, будет ли автоматически разрешен вызов document.requestStorageAccess()
:
Используйте метод hasStorageAccess()
При первой загрузке сайта он может использовать метод hasStorageAccess()
, чтобы проверить, предоставлен ли уже доступ к сторонним файлам cookie.
// Set a hasAccess boolean variable which defaults to false.
let hasAccess = false;
async function handleCookieAccessInit() {
if (!document.hasStorageAccess) {
// Storage Access API is not supported so best we can do is
// hope it's an older browser that doesn't block 3P cookies.
hasAccess = true;
} else {
// Check whether access has been granted using the Storage Access API.
hasAccess = await document.hasStorageAccess();
if (!hasAccess) {
// Handle the lack of access (covered later)
}
}
if (hasAccess) {
// Use the cookies.
}
}
handleCookieAccessInit();
API доступа к хранилищу предоставляет доступ к хранилищу документа iframe только после того, как он вызывает requestStorageAccess(),
поэтому hasStorageAccess()
может изначально возвращать значение false, например, если пользователь по умолчанию блокирует сторонние файлы cookie. (Однако пользовательские настройки для конкретного сайта также могут разрешать доступ к файлам cookie на определенном сайте, даже если пользователь по умолчанию блокирует сторонние файлы cookie.) Доступ к хранилищу с использованием этого API сохраняется при навигации по тому же источнику внутри iframe специально для того, чтобы разрешить перезагрузку после предоставления доступа для страниц, которые требуют присутствия файлов cookie в первоначальном запросе HTML-документа.
Используйте requestStorageAccess()
Если у iframe нет доступа, возможно, ему потребуется запросить доступ с помощью метода requestStorageAccess()
:
if (!hasAccess) {
try {
await document.requestStorageAccess();
} catch (err) {
// Access was not granted and it may be gated behind an interaction
return;
}
}
При первом запросе пользователю может потребоваться подтвердить этот доступ с помощью запроса браузера, после чего обещание будет разрешено или будет отклонено, что приведет к исключению, если используется await
.
Во избежание злоупотреблений это приглашение браузера будет отображаться только после взаимодействия с пользователем. Вот почему requestStorageAccess()
изначально необходимо вызывать из обработчика событий, активируемых пользователем, а не сразу при загрузке iframe:
async function doClick() {
// Only do this extra check if access hasn't already been given
// based on the hasAccess variable.
if (!hasAccess) {
try {
await document.requestStorageAccess();
hasAccess = true; // Can assume this was true if requestStorageAccess() did not reject.
} catch (err) {
// Access was not granted.
return;
}
}
if (hasAccess) {
// Use the cookies
}
}
document.querySelector('#my-button').addEventListener('click', doClick);
Если вам нужно использовать локальное хранилище вместо файлов cookie, вы можете сделать следующее:
let handle = null;
async function doClick() {
if (!handle) {
try {
handle = await document.requestStorageAccess({localStorage: true});
} catch (err) {
// Access was not granted.
return;
}
}
// Use handle to access unpartitioned local storage.
handle.localStorage.setItem('foo', 'bar');
}
document.querySelector('#my-button').addEventListener('click', doClick);
Запросы на разрешение
Когда пользователь нажимает кнопку в первый раз, в большинстве случаев автоматически появляется приглашение браузера, обычно в адресной строке. На следующем снимке экрана показан пример приглашения Chrome, но другие браузеры имеют аналогичный пользовательский интерфейс:

При определенных обстоятельствах запрос может быть пропущен браузером, и разрешение будет предоставлено автоматически:
- Если страница и iframe использовались в течение последних 30 дней после принятия запроса.
- Если встроенный iframe является частью набора связанных веб-сайтов .
- Если FedCM используется в качестве сигнала доверия для доступа к хранилищу.
- В Firefox приглашение также пропускается для известных веб-сайтов (тех, с которыми вы взаимодействовали на верхнем уровне) в течение первых пяти попыток.
Альтернативно, метод может быть автоматически отклонен без отображения подсказки при определенных обстоятельствах:
- Если пользователь ранее не посещал и не взаимодействовал с сайтом, которому принадлежит iframe как документ верхнего уровня, а не в iframe. Это означает, что API доступа к хранилищу полезен только для встроенных сайтов, которые пользователи ранее посещали в собственном контексте.
- Если метод
requestStorageAccess()
вызывается вне события взаимодействия с пользователем без предварительного утверждения запроса после взаимодействия.
Хотя пользователю будет предложено при первом использовании, последующие посещения могут разрешить requestStorageAccess()
без запроса и без вмешательства пользователя в Chrome и Firefox. Обратите внимание, что Safari всегда требует взаимодействия с пользователем.
Поскольку доступ к файлам cookie и хранилищу может быть предоставлен без запроса или взаимодействия с пользователем, часто можно получить неразделенный доступ к файлам cookie или хранилищу до взаимодействия с пользователем в браузерах, которые это поддерживают (Chrome и Firefox), вызвав requestStorageAccess()
при загрузке страницы. Это может позволить вам получить немедленный доступ к неразделенным файлам cookie и хранилищу и обеспечить более полный опыт, даже до того, как пользователь начнет взаимодействовать с iframe. В некоторых ситуациях это может оказаться более удобным для пользователя, чем ожидание взаимодействия с пользователем.
FedCM как сигнал доверия для SAA
FedCM (федеративное управление учетными данными) — это подход к федеративным службам идентификации, обеспечивающий сохранение конфиденциальности (например, «Войти с помощью...»), который не использует сторонние файлы cookie или навигационные перенаправления.
Когда пользователь входит в систему проверяющей стороны (RP), которая имеет встроенный контент от стороннего поставщика удостоверений (IdP) с помощью FedCM, встроенный контент IdP может автоматически получить доступ к хранилищу своих собственных неразделенных файлов cookie верхнего уровня. Чтобы включить автоматический доступ к хранилищу с помощью FedCM, должны быть выполнены следующие условия:
- Аутентификация FedCM (состояние входа пользователя) должна быть активной.
- RP согласился, установив разрешение
identity-credentials-get
, например:
<iframe src="https://idp.example" allow="identity-credentials-get"></iframe>
Например, iframe idp.example
встроен в rp.example
. Когда пользователь входит в систему с помощью FedCM, iframe idp.example
может запросить доступ к хранилищу для своих собственных файлов cookie верхнего уровня.
rp.example
выполняет вызов FedCM для входа пользователя в систему с помощью поставщика удостоверений idp.example
:
// The user will be asked to grant FedCM permission.
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://idp.example/fedcm.json',
clientId: '123',
}],
},
});
После входа пользователя в систему IdP может вызвать requestStorageAccess()
из iframe idp.example
, если RP явно разрешил это с помощью Permissions Policy . Встроенному файлу будет автоматически предоставлен доступ к хранилищу его собственного файла cookie верхнего уровня без активации пользователя или необходимости получения другого запроса на разрешение :
// Make this call within the embedded IdP iframe:
// No user gesture is needed, and the storage access will be auto-granted.
await document.requestStorageAccess();
// This returns `true`.
const hasAccess = await document.hasStorageAccess();
Разрешение будет предоставлено автоматически только в том случае, если пользователь вошел в систему с помощью FedCM. Если аутентификация неактивна, для предоставления доступа к хранилищу применяются стандартные требования SAA .
Последующая загрузка с помощью заголовков доступа к хранилищу
Заголовки доступа к хранилищу — рекомендуемый и более эффективный способ загрузки встроенного контента, включая ресурсы, не относящиеся к iframe. Эта функция доступна в Chrome 133. Благодаря заголовкам доступа к хранилищу браузер может распознавать, когда пользователь уже предоставил разрешение storage-access
стороннему источнику в текущем контексте, и может загружать ресурсы с доступом к неразделенным файлам cookie во время последующих посещений.
Поток заголовков доступа к хранилищу
При использовании заголовков доступа к хранилищу последующие посещения страниц будут запускать следующий поток:
- Пользователь ранее посещал
website.example
, в который встроен ресурсcalendar.example
, и предоставилstorage-access
с помощью вызоваdocument.requestStorageAccess()
. - Пользователь снова посещает
website.example
, в который встроен ресурсcalendar.example
. Этот запрос пока не имеет доступа к файлу cookie, как раньше. Однако пользователь ранее предоставил разрешениеstorage-access
, и выборка включает заголовокSec-Fetch-Storage-Access: inactive
, указывающий, что доступ к неразделенным файлам cookie доступен, но не активирован. - Сервер
calendar.example
отвечает сообщениемActivate-Storage-Access: retry; allowed-origin='<origin>'
(в данном случае<origin>
будетhttps://website.example
), чтобы указать, что выборка ресурса требует использования неразделенных файлов cookie с разрешениемstorage-access
. - Браузер повторяет запрос, на этот раз включая неразделенные файлы cookie (активируя разрешение
storage-access
для этой выборки и последующих выборок). - Сервер
calendar.example
отвечает персонализированным содержимым iframe. Ответ включает заголовокActivate-Storage-Access: load
, указывающий, что браузер должен загружать контент с активированным разрешениемstorage-access
(другими словами, загружать с неразделенным доступом к файлам cookie, как если бы был вызванdocument.requestStorageAccess()
). - Пользовательский агент загружает содержимое iframe с неразделенным доступом к файлам cookie, используя разрешение
storage-access
. После этого шага виджет может работать как положено.

Используйте заголовки доступа к хранилищу
В следующей таблице перечислены заголовки доступа к хранилищу.
Поток | Заголовок | Ценить | Описание |
---|---|---|---|
Запрос | Sec-Fetch-Storage-Access Примечание. Браузер автоматически отправляет этот заголовок в межсайтовых запросах, включающих учетные данные (например, new Request('request.example', { credentials: 'include' }); ). | none | У Embed нет разрешения на доступ к хранилищу. |
inactive | Внедрение имеет разрешение, но не использует его. Запрос также должен включать заголовок Origin . | ||
active | Embed имеет неразделенный доступ к файлам cookie. | ||
Ответ | Activate-Storage-Access | load | Указывает браузеру предоставить разработчику доступ к неразделенным файлам cookie для запрошенного ресурса. Включение этого заголовка эквивалентно вызову document.requestStorageAccess() , если было предоставлено разрешение storage-access . Это означает, что пользователю не будет отображаться никаких дополнительных запросов. |
retry | Указывает браузеру активировать разрешение на доступ к хранилищу, а затем повторить запрос. | ||
allowed-origin | <origin> | Указывает, какому источнику разрешено инициировать запросы с учетными данными (например, https://site.example или * ). |
Например, заголовки доступа к хранилищу можно использовать для загрузки изображения изображения от стороннего производителя:
// On the client side
<img src="https://server.example/image">
В этом случае server.example
должен реализовать на стороне сервера следующую логику:
app.get('/image', (req, res) => {
const storageAccessHeader = req.headers['sec-fetch-storage-access'];
if (storageAccessHeader === 'inactive') {
// The user needs to grant permission, trigger a prompt
// Check if the requesting origin is allowed
// to send credentialed requests to this server.
// Assuming the `validate_origin(origin)` method is previously defined:
if (!validate_origin(req.headers.origin)) {
res.status(401).send(req.headers.origin +
' is not allowed to send credentialed requests to this server.');
return;
}
// 'retry' header value indicates that the content load request should be re-sent after the user has granted permissions
res.set('Activate-Storage-Access', `retry; allowed-origin='${req.headers.origin}'`);
res.status(401).send('This resource requires storage access. Please grant permission.');
} else if (storageAccessHeader === 'active') {
// User has granted permission, proceed with access
res.set('Activate-Storage-Access', 'load');
// Include the actual iframe content here
res.send('This is the content that requires cookie access.');
} else {
// Handle other cases (e.g., 'Sec-Fetch-Storage-Access': 'none')
}
});
Демо-версия API доступа к хранилищу внедряет сторонний контент (включая изображения, не относящиеся к iframe) с помощью заголовков доступа к хранилищу.
Используйте запрос разрешения storage-access
Чтобы проверить, может ли доступ быть предоставлен без взаимодействия с пользователем, вы можете проверить статус разрешения storage-access
и выполнить вызов requestStoreAccess()
раньше, если никаких действий пользователя не требуется, вместо того, чтобы вызывать его и вызывать сбой, когда требуется взаимодействие.
Это также позволяет вам потенциально удовлетворить потребность в предварительном запросе, отображая различное содержимое, например кнопку входа в систему.
Следующий код добавляет проверку разрешений storage-access
к предыдущему примеру:
// Set a hasAccess boolean variable which defaults to false except for
// browsers which don't support the API - where we assume
// such browsers also don't block third-party cookies.
let hasAccess = false;
async function hasCookieAccess() {
// Check if Storage Access API is supported
if (!document.requestStorageAccess) {
// Storage Access API is not supported so best we can do is
// hope it's an older browser that doesn't block 3P cookies.
return true;
}
// Check if access has already been granted
if (await document.hasStorageAccess()) {
return true;
}
// Check the storage-access permission
// Wrap this in a try/catch for browsers that support the
// Storage Access API but not this permission check
// (e.g. Safari and earlier versions of Firefox).
let permission;
try {
permission = await navigator.permissions.query(
{name: 'storage-access'}
);
} catch (error) {
// storage-access permission not supported. Assume no cookie access.
return false;
}
if (permission) {
if (permission.state === 'granted') {
// Permission has previously been granted so can just call
// requestStorageAccess() without a user interaction and
// it will resolve automatically.
try {
await document.requestStorageAccess();
return true;
} catch (error) {
// This shouldn't really fail if access is granted, but return false
// if it does.
return false;
}
} else if (permission.state === 'prompt') {
// Need to call requestStorageAccess() after a user interaction
// (potentially with a prompt). Can't do anything further here,
// so handle this in the click handler.
return false;
} else if (permission.state === 'denied') {
// Not used: see https://github.com/privacycg/storage-access/issues/149
return false;
}
}
// By default return false, though should really be caught by earlier tests.
return false;
}
async function handleCookieAccessInit() {
hasAccess = await hasCookieAccess();
if (hasAccess) {
// Use the cookies.
}
}
handleCookieAccessInit();
Изолированные iframe в песочнице
При использовании API доступа к хранилищу в изолированных iframes требуются следующие разрешения песочницы:
- Для разрешения доступа к API доступа к хранилищу требуется
allow-storage-access-by-user-activation
. -
allow-scripts
необходим, чтобы разрешить использование JavaScript для вызова API. -
allow-same-origin
требуется, чтобы разрешить доступ к файлам cookie того же происхождения и другим хранилищам.
Например:
<iframe sandbox="allow-storage-access-by-user-activation
allow-scripts
allow-same-origin"
src="..."></iframe>
Требования к файлам cookie
Чтобы к межсайтовым файлам cookie можно было получить доступ с помощью API доступа к хранилищу в Chrome, необходимо установить следующие два атрибута:
-
SameSite=None
— требуется, чтобы пометить файл cookie как межсайтовый. -
Secure
— обеспечивает доступ только к файлам cookie, установленным сайтами HTTPS.
В Firefox и Safari для файлов cookie по умолчанию установлено значение SameSite=None
, и они не ограничивают SAA для Secure
файлов cookie, поэтому эти атрибуты не являются обязательными. Рекомендуется явно указывать атрибут SameSite
и всегда использовать Secure
файлы cookie.
Доступ к странице верхнего уровня
API доступа к хранилищу предназначен для обеспечения доступа к сторонним файлам cookie во встроенных iframe.
Существуют также другие случаи использования, когда страница верхнего уровня требует доступа к сторонним файлам cookie. Например, изображения или скрипты, использование которых ограничено файлами cookie, и которые владельцы сайтов могут захотеть включить непосредственно в документ верхнего уровня, а не в iframe. Чтобы решить эту проблему, Chrome предложил расширение API доступа к хранилищу , которое добавляет метод requestStorageAccessFor()
.
Метод requestStorageAccessFor()
Метод requestStorageAccessFor()
работает аналогично requestStorageAccess()
но для ресурсов верхнего уровня. Его можно использовать только для сайтов в наборе связанных веб-сайтов , чтобы предотвратить предоставление общего доступа к сторонним файлам cookie.
Подробнее о том, как использовать requestStorageAccessFor()
читайте в разделе «Наборы связанных веб-сайтов: руководство для разработчиков» .
Запрос разрешения top-level-storage-access
Browser Support
Подобно разрешению storage-access
, существует разрешение top-level-storage-access
позволяющее проверить, можно ли предоставить доступ для requestStorageAccessFor()
.
Чем отличается API доступа к хранилищу при использовании с RWS?
Когда наборы связанных веб-сайтов используются с API доступа к хранилищу, доступны определенные дополнительные возможности, подробно описанные в следующей таблице:
Без РВС | С РВС | |
---|---|---|
Требуется жест пользователя, чтобы инициировать запрос на доступ к хранилищу. | ||
Требуется, чтобы пользователь посетил запрошенное хранилище в контексте верхнего уровня, прежде чем предоставить доступ. | ||
Запрос пользователя при первом посещении можно пропустить. | ||
requestStorageAccess не требуется вызывать, если доступ был ранее предоставлен | ||
Автоматически предоставляет доступ к другим доменам на связанном веб-сайте. | ||
Поддерживает requestStorageAccessFor для доступа к страницам верхнего уровня. |
Демо: настройка и доступ к файлам cookie
В следующей демонстрации показано, как можно получить доступ к файлу cookie, установленному вами на первом экране демонстрации, во встроенном фрейме на втором сайте демонстрации:
хранилище-доступ-api-demo.glitch.me
Для демонстрации требуется браузер с отключенными сторонними файлами cookie:
- Chrome 118 или более поздней версии с установленным флагом
chrome://flags/#test-third-party-cookie-phaseout
и перезапущенным браузером. - Firefox
- Сафари
Демо: настройка локального хранилища
В следующей демонстрации показано, как получить доступ к неразделенным широковещательным каналам из стороннего iframe с помощью API доступа к хранилищу:
https://saa-beyond-cookies.glitch.me/
Для демонстрации требуется Chrome 125 или более поздней версии с включенным флагом поэтапного отказа от сторонних файлов cookie .
Ресурсы
- Прочтите спецификацию , предоставляющую доступ к сторонним файлам cookie, или следуйте ей и поднимайте вопросы .
- Прочтите спецификацию , предоставляющую неразделенный доступ к хранилищу, или следуйте ей и поднимайте вопросы .
- Документация и руководство по API.
- Документация Chrome по использованию API доступа к хранилищу в наборах связанных веб-сайтов