Digital Leadership & Soft Skills

Cookies, sessionStorage, localStorage: В чем разница

Опубликовано by Pavel Nakonechnyy on (изменено: ) в Web development.
Cookies, sessionStorage, localStorage: В чем разница

Этот пост посвящен трём различным возможностям хранения данных в браузере. Ими являются куки и два вида хранилищ, которые можно использовать через 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 отслеживания.

3 096