Cookies, sessionStorage, localStorage: В чем разница
Опубликовано by Pavel Nakonechnyy on (изменено: ) в Web development.Этот пост посвящен трём различным возможностям хранения данных в браузере. Ими являются куки и два вида хранилищ, которые можно использовать через JavaScript API в коде фронтенда. Они используются для аутентификации, инструментов аналитики вроде Google Analytics и множества других вещей. Так что давайте взглянем на то, как оно работает!
sessionStorage
Session Storage может быть немного сложным для понимания, потому что он называется хранилищем сессии. И в данном случае, сессия, к которой мы обращаемся — это конкретная вкладка браузера, а не браузер или окно.
Поэтому не стоит использовать этот тип хранилища для работы с долгосрочными данными. Например, с сессиями аутентификации. Когда вы входите в Facebook, Facebook запоминает вас, несмотря на то, что вы закрыли страницу и открыли её снова. Здесь используются Cookies, а не Session Storage.
Главное преимущество sessionStorage
перед глобальной переменной JavaScript в том, что оно сохраняется после перезагрузки страницы. Поэтому, если у вас есть несколько страниц, отрисованных на сервере, то вы можете сохранить какую-то информацию на клиенте, не забывая, что должна использоваться лишь одна вкладка. В течение длительного периода времени, особенно до появления localStorage
и сложных алгоритмов отслеживания изменений для фронтенда, это было очень нужной фичей!
Волатильность хранилища — характеристика способа хранения, отражающая способность хранилища сохранять данные в течение длительного времени. Волатильность в переводе с английского языка означает изменчивость. Термин является полной противоположностью понятиям стабильность и постоянство.
sessionStorage
— очень волатильное хранилище. Оно не хранится долго. К нему можно относиться, как к текстовому документу без кнопки «Сохранить». Все в нем хранящееся превратится в прах, стоит пользователю закрыть вкладку браузера. Ну, почти. Чисто технически кое-какой JavaScript может перед этим отослать данные на удаленный сервер, который запомнит их для вас.
В любом случае давайте попробуем:
sessionStorage.setItem("name", "Jonathan");
let data = sessionStorage.getItem("name");
console.log(data);
Если вы скопируете этот код в консоль или вставите в простой <script>
и откроете через простой веб сервер, вы сможете увидеть Jonathan
в вашей консоли. Помимо этого, если вы откроете инструменты разработчика и посмотрите на вкладку Storage
в Firefox или Application
в Chrome, а затем переключитесь на вкладку SessionStorage
, то вы увидите запись name = Jonathan.
Если вы хотите удалить сохраненную переменную, то можете использовать sessionStorage.removeItem('name')
или просто sessionStorage.clear();
.
Почитать больше о sessionStorage в Mozilla Development Network.
localStorage
Давайте поговорим о чем-нибудь более занимательном: localStorage
. В отличие от sessionStorage
оно сохраняет свои данные для всего приложения, т.е. вашего сайта. В целях безопасности браузер прикрепляет записи хранилища к домену сайта, так что вы можете хранить там относительно секретную информацию. Другие сайты не смогут её прочитать.
Когда я говорю об относительно секретной информации, то не подразумеваю пароли. Все сохраненные в sessionStorage
данные можно увидеть в инспекторе без какого-либо шифрования. В этом хранилище можно хранить секретный токен со сроком действия или JSON Web Token, но и здесь Сookie будет более уместен.
Вы спросите, почему в localStorage
? У localStorage
нет времени очистки. Потенциально эта информация будет храниться в браузере вечно. Пользователь может удалить её вручную, но было бы неразумно ожидать от него таких странных вещей.
Увы, у этой функции есть определенные ограничения. Возможность записи в localStorage
доступна не всегда. Например, iOS Safari вернёт ошибку при попытке записать в localStorage
, если браузер находится в приватном режиме:
Error: QUOTA_EXCEEDED_ERR: DOM Exception 22
Для работы с localStorage используются методы getItem
и setItem
. Вот хороший пример с использованием localStorage и JQuery:
jQuery("#toggleDark").click(function () {
jQuery("body").toggleClass("dark");
if (jQuery(this).text() == "Тёмная тема") {
jQuery(this).text("Светлая тема")
localStorage.setItem("darkTheme", true);
}
else {
jQuery(this).text("Тёмная тема");
localStorage.setItem("darkTheme", false);
}
});
if (localStorage.getItem("darkTheme") === "true") {
jQuery("body").toggleClass("dark");
jQuery("#toggleDark").text("Светлая тема");
}
Помимо крутости самого факта, что вы можете работать с setItem
, getItem
и функциями удаления, вы можете копировать state вашего приложения в localStorage
, чтобы при следующем запуске восстановить его оттуда (если вы пересылаете много данных туда и обратно), а уже потом думать над доставкой up-to-date информации пользователю. Важно запомнить, что localStorage работает не со всеми типами данных, поэтому вам понадобится подумать над сериализацией и десериализацией.
Cookies
Теперь к самой сладкой части. Cookies стали привычным объектом ограничений законов о приватности и используются на всех сайтах с авторизацией по логину и паролю. Cookies тоже являются domain specific, то есть привязаны только к конкретному домену, могут храниться очень долго. Но, в отличие от прошлых хранилищ, они пересылаются с каждым исходящим HTTP/HTTPS запросом на сервер. Их можно читать и записывать со стороны сервера. При записи они будут добавлены в HTTP ответ, чтобы браузер пользователя их запомнил.
Как очень упрощенный пример, представьте, что вы подходите к ларьку с мороженым, и вас встречает продавец с бумажной табличкой с некоторыми символами на ней. Допустим, 5axhz
. И теперь, каждый раз обращаясь к этому сотруднику, вы будете добавлять эти символы к вашим запросам.
О, это выглядит неплохо. С каким оно вкусом? 5axhz
Клубничное
О. Тогда я бы взял два таких. 5axhz
На самом деле, два таких и одно ванильное. 5axhz
Но существует проблема приватности. Теперь каждый ресторан, который показывает вам картинку того ларька с мороженым, позволит вашему первоначальному продавцу мороженого узнать о том, что вы смотрите на фотографии мороженого, хотя вы даже не близко к нему.
В реальной жизни печатные фотографы не могут узнать, просматриваются ли они конкретным человеком (пока?). Но в интернете доступный извне ресурс может сообщить владельцу, что он просмотрен кем-то. И при необходимости идентифицировать этого человека по Cookie. Несмотря на то, что он вышел из аккаунта. Именно этим обусловлен общественный скептицизм к технологии. Аналитика Google, используемая сейчас практически на каждом сайте, передает компании Google данные о ваших просмотрах по всему интернету.
Работа с Cookies в JavaScript
На фронтенде вы будете работать с cookies через объект document.cookie
. Давайте попробуем поработать с cookies.
document.cookie = "my_favourite_ice_cream" + "=" + "vanilla";
document.cookie = "my_favourite_burger" + "=" + "cheeseburger";
console.log(document.cookie);
// my_favourite_ice_cream=vanilla;
// my_favourite_burger=cheeseburger
Как вы могли заметить, запись в document.cookie работает непривычно. Каждое присвоение значения переменной на самом деле добавляет ключ в хранилище. А при чтении переменной пары ключ-значение в cookies разделены точкой с запятой, что может сделать работу с ними несколько сложнее. Эта проблема решается простыми и удобными библиотеками вроде js-cookie
.
Без указания параметра expires, запись удалится после окончания текущей сессии (вкладки браузера).
Мы также можем посмотреть текущие Cookies, используя инспектор браузера, аналогично тому, как мы делали с прошлыми хранилищами. Только в этот раз откроем вкладку Cookies.
Узнать подробности работы cookies вы можете в W3SCHOOLS.
Работа с Cookies с сервера
Cookies могут быть заданы и сервером, т.е. вам не нужно пересылать данные с сервера, чтобы потом выполнить JS на клиенте. Для передачи Cookies клиенту можно просто включить в ответ HTTP заголовки:
HTTP/2.0 200 OK
Content-type: text/html
Set-Cookie: favourite_hero=aquaman
Set-Cookie: favourite_khal=drogo
Даже если ваш web фреймворк позволяет вам работать с HTTP заголовками напрямую, не стоит этого делать. Обычно для работы с cookies есть заранее спроектированные функции. Это поможет избежать вам многих ошибок и упростит работу с технологией. Например, библиотека вернёт ошибку, если ваши ключи/значения слишком длинны. В PHP для записи cookie используется функция стандартной библиотекиsetcookie
. Используется так:
setcookie( "previous_orders", "65" );
Или res.cookie в Express (Node.JS):
// express
res.cookie("cookieName", "cookieValue", { maxAge: 50000 });
В этой статье мы не рассмотрели indexedDB. У неё также множество различных возможностей для хранения данных.
Также мы не рассмотрели инструкции по безопасности и флаги для cookie. Их следует использовать для уменьшения рисков распространения конфиденциальной информации. Необходимо ознакомиться с ними, прежде чем размещать в Cookies критичную информацию.
Итоги
Мы коротко познакомились с тремя различными методами хранения данных в браузере пользователя. Мы можем ими воспользоваться, если нам потребуется записать JSON Web Token или ID отслеживания.