Павел Наконечный

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

Опубликовано (изменено: ) в Веб-разработка.

Этот пост посвящен трём различным возможностям хранения данных в браузере. Ими являются куки и два вида хранилищ, которые можно использовать через JavaScript API в коде фронтенда. Они используются для аутентификации, инструментов аналитики вроде Google Analytics и множества других вещей. Так что давайте взглянем на то, как оно работает!

sessionStorage

Session Storage может быть немного сложным для понимания, потому что он называется хранилищем сессии. И в данном случае, сессия, к которой мы обращаемся — это конкретная вкладка браузера, а не браузер или окно.

Поэтому не стоит использовать этот тип хранилища для работы с долгосрочными данными. Например, с сессиями аутентификации. Когда вы входите в Facebook, Facebook запоминает вас, несмотря на то, что вы закрыли страницу и открыли её снова. Здесь используются Cookies, а не Session Storage.

Главное преимущество sessionStore перед глобальной переменной JavaScript в том, что оно сохраняется после перезагрузки страницы. Поэтому, если у вас есть несколько страниц, отрисованных на сервере, то вы можете сохранить какую-то информацию на клиенте, не забывая, что должна использоваться лишь одна вкладка. В течение длительного периода времени, особенно до появления localStorage и сложных алгоритмов отслеживания изменений для фронтенда, это было очень нужной фичей!

Волатильность хранилища –  характеристика способа хранения, отражающая способность хранилища сохранять данные в течение длительного времени. Волатильность в переводе с английского языка означает изменчивость. Термин является полной противоположностью понятиям стабильность и постоянство.

sessionStore – очень волатильное хранилище. Оно не хранится долго. К нему можно относиться, как к текстовому документу без кнопки “Сохранить”. Все в нем хранящееся превратится в прах, стоит вам закрыть вкладку браузера. Ну, почти. Чисто технически кое-какой 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 оно сохраняет свои данные для всего приложения, т.е. вашего сайта. С целью безопасности браузер прикрепляет записи к домену сайта, так что вы можете хранить там относительно секретную информацию. Другие сайты не смогут её прочитать.

Когда я говорю об относительно секретной информации, то не подразумеваю пароли. Ведь сохраненные данные в любой момент можно увидеть в инспекторе. Но там можно хранить секретный токен со сроком действия (но здесь cookie здесь будет более уместно) или JSON Web Token.

Вы спросите, почему в 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 в vanilla 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 вы можете в W3SCHOOLS.

Мы также можем посмотреть текущие Cookies, используя инспектор браузера, аналогично тому, как мы делали с прошлыми хранилищами. Только в этот раз откроем вкладку Cookies.

Работа с Cookies с сервера

Cookies могут быть также заданы и сервером, т.е. вам не нужно пересылать данные с сервера, чтобы потом выполнить JS на клиенте. Для передачи Cookies клиенту можно просто включить в ответ HTTP заголовки:

HTTP/2.0 200 OK
Content-type: text/html
Set-Cookie: favourite_hero=aquaman
Set-Cookie: favourite_khal=drogo

Даже если вы можете работать напрямую с HTTP заголовками с вашим web фреймворком, не стоит этого делать. Обычно для работы с cookies есть заранее спроектированные функции. Это поможет избежать вам многих ошибок и упростит работу с технологией. Например, они возвращают ошибки, если ваши ключи/значения слишком длинны. Например , в PHP это функцияsetcookie. Используется так:

setcookie( "previous_orders", "65" );

Или res.cookie в Express:

// express
res.cookie("cookieName", "cookieValue", { maxAge: 50000 });

Итоги

Мы коротко познакомились с тремя различными методами хранения данных в браузере пользователя. Мы можем ими воспользоваться, если нам потребуется записать JSON Web Token или ID отслеживания.

В этой статье мы не рассмотрели indexedDB. У неё также множество различных возможностей для хранения данных. Также мы не рассмотрели такие тонкости, как инструкции по безопасности и флаги для cookie. Их следует использовать для уменьшения рисков распространения конфиденциальной информации. Почитайте о них прежде чем размещать в Cookies критичную информацию.

Если вы хотите читать больше подобного контента, то можете подписаться на меня в Twitter, ВКонтакте или Telegram.


Обновлено 07.05.2021

Источники:

Просмотров:

Вас также может заинтересовать