Использование API доступа к хранилищу
API доступа к хранилищу может использоваться встроенными документами с других сайтов для проверки наличия доступа к сторонним cookie и неразделенному состоянию, а при отсутствии доступа — для запроса доступа. Рассмотрим краткий пример типичного сценария использования.
Примечание: Когда в документации API доступа к хранилищу упоминаются сторонние cookie, подразумеваются неразделенные сторонние cookie.
Примечания по использованию
API доступа к хранилищу предназначен для того, чтобы встроенное содержимое могло запросить доступ к сторонним cookie и неразделенному состоянию. Большинство современных браузеров по умолчанию блокируют такой доступ для защиты конфиденциальности пользователя. Так как встроенному содержимому неизвестно, как браузер будет себя вести в данном случае, всегда лучше предварительно проверить, есть ли у встроенного <iframe> доступ к хранилищу, прежде чем пытаться читать или записывать cookie. Это особенно важно для доступа к Document.cookie, так как при блокировке доступа к сторонним cookie браузер часто возвращает пустой список cookie.
В примере ниже показано, как встроенный элемент <iframe> с другого сайта может получить доступ к сторонним cookie и неразделенному состоянию в соответствии с политикой браузера, которая обычно блокирует к ним доступ.
Разрешение встроенному
Прежде всего, если <iframe> имеет песочницу, веб-сайт-вкладыш должен добавить в атрибут sandbox токен песочницы, чтобы запросы API доступа к хранилищу были успешны, а также allow-scripts и allow-same-origin для выполнения скрипта, вызывающего API и выполняющего его в источнике, который может иметь cookie и состояние:
<iframe
sandbox="allow-storage-access-by-user-activation
allow-scripts
allow-same-origin">
…
</iframe>
Проверка и запрос доступа к хранилищу
Теперь перейдем к коду, выполняющемуся внутри встроенного документа. В этом коде:
- Сначала мы используем обнаружение функций (
if (document.hasStorageAccess) {}) для проверки поддержки API. Если API не поддерживается, мы выполняем код, который все равно пытается получить доступ к cookie, надеясь, что это сработает. Любой код, который обращается к cookie, должен быть разработан с учетом возможных сбоев. - Если API поддерживается, мы вызываем
document.hasStorageAccess(). - Если этот вызов возвращает
true, значит, у этого<iframe>уже есть доступ, и мы можем сразу выполнить код, который получает доступ к cookie и состоянию. - Если этот вызов возвращает
false, мы вызываемPermissions.query(), чтобы проверить, был ли уже предоставлен доступ к сторонним cookie и неразделенному состоянию (например, другому встроенному содержимому с того же сайта). Мы заключаем весь этот блок вtry...catch, потому что некоторые браузеры не поддерживают разрешение"storage-access", что может вызвать исключение при вызовеquery(). Если исключение возникнет, мы сообщим об этом в консоль и все равно попробуем выполнить код, обращаясь к cookie. - Если состояние разрешения равно
"granted", мы сразу вызываемdocument.requestStorageAccess(). Этот вызов автоматически разрешится, сэкономив пользователю время, после чего мы можем выполнить код, который обращается к cookie и состоянию. - Если состояние разрешения равно
"prompt", мы вызываемdocument.requestStorageAccess()после взаимодействия пользователя. Этот вызов может вызвать диалоговое окно для пользователя. Если этот вызов разрешится, мы можем выполнить код, который обращается к cookie и состоянию. - Если состояние разрешения равно
"denied", пользователь отказался предоставить доступ к сторонним cookie или неразделенному состоянию, и наш код не может их использовать.
function doThingsWithCookies() {
document.cookie = "foo=bar"; // set a cookie
}
function doThingsWithLocalStorage(handle) {
handle.localStorage.setItem("foo", "bar"); // set a local storage key
}
async function handleCookieAccess() {
if (!document.hasStorageAccess) {
// This browser doesn't support the Storage Access API
// so let's just hope we have access!
doThingsWithCookies();
} else {
const hasAccess = await document.hasStorageAccess();
if (hasAccess) {
// We have access to third-party cookies, so let's go
doThingsWithCookies();
// If we want to modify unpartitioned state, we need to request a handle.
const handle = await document.requestStorageAccess({
localStorage: true,
});
doThingsWithLocalStorage(handle);
} else {
// Check whether third-party cookie access has been granted
// to another same-site embed
try {
const permission = await navigator.permissions.query({
name: "storage-access",
});
if (permission.state === "granted") {
// If so, you can just call requestStorageAccess() without a user interaction,
// and it will resolve automatically.
const handle = await document.requestStorageAccess({
cookies: true,
localStorage: true,
});
doThingsWithLocalStorage(handle);
doThingsWithCookies();
} else if (permission.state === "prompt") {
// Need to call requestStorageAccess() after a user interaction
btn.addEventListener("click", async () => {
try {
const handle = await document.requestStorageAccess({
cookies: true,
localStorage: true,
});
doThingsWithLocalStorage(handle);
doThingsWithCookies();
} catch (err) {
// If there is an error obtaining storage access.
console.error(`Error obtaining storage access: ${err}.
Please sign in.`);
}
});
} else if (permission.state === "denied") {
// User has denied third-party cookie access, so we'll
// need to do something else
}
} catch (error) {
console.log(`Could not access permission state. Error: ${error}`);
doThingsWithCookies(); // Again, we'll have to hope we have access!
}
}
}
}
Примечание: Запросы requestStorageAccess() автоматически отклоняются, если встроенное содержимое не обрабатывает действие пользователя, такое как тап или клик (временная активация), или если разрешение было предоставлено ранее. Если разрешение не было предоставлено ранее, запросы requestStorageAccess() должны выполняться внутри обработчика событий, основанного на действиях пользователя, как показано выше.
Связанные наборы сайтов
Функция Chrome-только связанных наборов сайтов может рассматриваться как механизм поэтапного улучшения, который работает совместно с API доступа к хранилищу, — поддерживающие браузеры предоставляют по умолчанию доступ к сторонним cookie и неразделенному состоянию между сайтами в одном наборе. Это означает, что не нужно проходить обычный процесс запроса разрешения от пользователя, описанный выше, что делает опыт пользователей сайтов в наборе более удобным.
Запрос доступа к хранилищу от основного сайта от имени встроенных ресурсов
API доступа к хранилищу позволяет встроенному документу запросить собственный доступ к сторонним cookie. Доступно дополнительный экспериментальный метод Document.requestStorageAccessFor(), предлагаемое расширение API доступа к хранилищу, которое позволяет основным сайтам запросить доступ к хранилищу от имени конкретных связанных источников.
Метод requestStorageAccessFor() решает проблемы при внедрении API доступа к хранилищу на основных сайтах, использующих изображения или скрипты с других сайтов, требующих cookie. Он может разрешить доступ к сторонним cookie для ресурсов с других сайтов, встроенных непосредственно на основной сайт, которые не могут запросить доступ к хранилищу самостоятельно, например, с помощью элементов <img> или <script>.
Для работы requestStorageAccessFor() оба вызывающие страницы верхнего уровня и ресурс, для которого запрашивается доступ к хранилищу, должны входить в один связанный набор сайтов.
Типичное использование requestStorageAccessFor() выглядит следующим образом (на этот раз на регулярном стиле promise, а не async/await):
navigator.permissions
.query({
name: "top-level-storage-access",
requestedOrigin: "https://example.com",
})
.then((permission) => {
if (permission.state === "granted") {
// Permission has already been granted
// No need to call requestStorageAccessFor() again, just start using cookies
doThingsWithCookies();
} else if (permission.state === "prompt") {
// Need to call requestStorageAccessFor() after a user interaction
btn.addEventListener("click", () => {
// Request storage access
rSAFor();
});
} else if (permission.state === "denied") {
// User has denied third-party cookie access, so we'll
// need to do something else
}
});
function rSAFor() {
if ("requestStorageAccessFor" in document) {
document.requestStorageAccessFor("https://example.com").then(
(res) => {
doThingsWithCookies();
},
(err) => {
// Handle errors
},
);
}
}
Примечание: В отличие от requestStorageAccess(), Chrome не проверяет наличие взаимодействия на основном документе в течение последних 30 дней при вызове requestStorageAccessFor(), так как пользователь уже на странице. Дополнительные сведения об этом поведении см. в разделе Отличия для разных браузеров > Chrome.
При запросе состояния разрешения для запросов доступа к хранилищу от имени другого источника имя разрешения отличается от остальных API доступа к хранилищу: "top-level-storage-access" вместо "storage-access". В приведенном выше коде используется следующий вызов:
navigator.permissions.query({
name: "top-level-storage-access",
requestedOrigin: "https://example.com",
});
для определения, было ли разрешение предоставлено для источника ранее, или нужно снова запросить доступ к cookie.
- Если состояние разрешения равно
"granted", мы можем начать использовать cookie;requestStorageAccessFor()уже был вызван, поэтому нет необходимости вызывать его снова. - Если состояние разрешения равно
"prompt", нам нужно вызватьdocument.requestStorageAccessFor("https://example.com")внутри действия пользователя, например, нажатия кнопки.
После предоставления разрешения на доступ к "top-level-storage-access" , запросы с других сайтов будут включать cookie, если они включают CORS / crossorigin, поэтому сайты могут захотеть подождать перед отправкой запроса. Такие запросы должны использовать параметр credentials: "include", а ресурсы должны содержать атрибут crossorigin="use-credentials".
Например:
function checkCookie() {
fetch("https://example.com/getcookies.json", {
method: "GET",
credentials: "include",
})
.then((response) => response.json())
.then((json) => {
// Do something
});
}
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API/Using