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

Перевод статьи Джонатана М. Хезей

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

sessionStorage

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

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

Главное преимущество sessionStore перед глобальной переменной JavaScript в том, что оно сохраняется после перезагрузки страницы. То если если у вас есть несколько Server-side rendered pages, то вы можете хранить некоторую информацию на клиенте, принимая во внимание, что используется одна вкладка. В течение длительного периода времени, особенно до появления 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 нет времени удаления. Потенциально, эта информация будет храниться в браузере вечно, или пока ваш javascript код не удалит ее. Так-то пользователь тоже может ее удалить, но было бы неразумно ожидать от него таких странных вещей.

Увы, есть некоторые ограничения с этой функций, и возможность записи в localStorage не всегда доступна. Например, iOS Safari возвращает ошибку при попытке записать в localStorage, когда бразуер находится в приватном режиме.

Error: QUOTA_EXCEEDED_ERR: DOM Exception 22

Помимо крутости самоо факта, что вы можете работать с setItem, getItem и функциями удаления, вы можете копировать state вашего приложения в localStorage, чтобы при следующем запуске восстановить его оттуда (если вы пересылаете много данных туда и обратно), а уже потом думать над доставкой up-to-date информации пользователю.

Cookies

Теперь, к самой сладкой части. Cookies вошли в СМИ в качестве объекта ограничений некоторыми законами о приватности. Cookies тоже являются domain specific, то есть привязаны только к вашему домену, могут храниться очень долго, и они, в отлчие от прошлых хранилищ, отправляются с каждым HTTP/HTTPS запросом к вашему сайту.

Как очень упрощенный пример, представьте, что вы подходите к ларьку с мороженым, и вас встречает продавец с бумажной табличкой с некоторыми символами на ней. Допустим, 5axhz. И теперь, каждый раз обращаясь к этому сотруднику, вы будете добавлять эти символы к вашим запросам.

О, это выглядит неплохо. С каким оно вкусом? 5axhz Клубничное О. Тогда я бы взял два таких. 5axhz На самом деле, два таких и одно ванильное. 5axhz

Проблема приватности состоит в том, что теперь каждый ресторан, который показывает вам картинку того ларька с мороженым, теперь позволит вашему первоначальному продавцу мороженого узнать о том, что вы смотрите на фотографии мороженого, хотя вы даже не близко к нему.

На данный момент в реальной жизни печатные фотографы не могут узнать, просматриваются ли они конкретным человеком (пока?). В интернете любой включенный извне ресурс может сообщить владельцу, что он просмотрен кем-то, и если этот кто-то уже смотрел ранее, то он может идентифицировать этого человека, несмотря на то, что он вышел из аккаунта.

Работа с 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

Как вы могли заметить, пары ключ-значение в cookies разделены точкой с запятой, что может сделать работу с ними несколько сложнее, но это решается простыми и удобными библиотеками вроде js-cookie.

Без указания expires, запись удалится после этой сессии (вкладки браузера).

Почитать о cookies вы можете в W3SCHOOLS.

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

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

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

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

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

setcookie( "previous_orders", "65" );

Или res.cookie в Express:

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

Итоги

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

Чего мы не изучили, так это indexedDB, которому будет посвящен отдельный пост, поскольку у него есть множество крутых фич тоже!

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

Спасибо за прочтение! Если у вас есть какие-то комментарии, добавления или вопросы, вы можете задать их в Telegram.

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

Небольшое послесловие: Да, я вернулся к старому домену sneakbug8.com, в основном из-за SEO и траста к сайту, возникшего у поисковиков и социальных сетей за год активного использования. И в результате вместо ожидаемой экоомии 700 рублей в год на домене, я выложился лишние 300 рублей на два .ru домена, которые просто редиректят сюда. Классно, правда? Ну да ладно, мне не жалко.

Опубликовано 2019-06-12 #javascript #frontend #web


Подписывайтесь в соц. сетях

Павел Наконечный © 2015-2019. Копирование и использование материалов только с указанием авторства и ссылкой на первоисточник.