Перейти к основному содержимому

Storage

Local Storage (локальное хранилище)​

Хранит данные бессрочно. Очищается только с помощью JavaScript или очистки кэша браузера. Хранит данные объёмом до 5 МБ, это самый большой объём из трёх вариантов хранилища. Не поддерживается старыми браузерами, например, IE 7 и ниже. Работает по правилу ограничения домена (same origin policy). То есть сохранённые данные доступны только для одного источника.

// взять
localStorage.getItem('some-ls-field');

// сохранить
localStorage.setItem('some-ls-field', someValue);

// удалить
localStorage.removeItem('some-ls-field');

// очистить localStorage
localStorage.clear();

Session Storage (сессионное хранилище)​

Хранит данные, пока продолжается текущая сессия. Когда пользователь закрывает браузер, данные становятся недоступными. Используется контекст браузера верхнего уровня, поэтому каждая вкладка браузера хранит уникальные данные. Объём данных больше чем в Cookie. Не поддерживается старыми браузерами, например, IE 7 и ниже.


Фрагмент данных, отправленный веб-сервером и хранимый на компьютере пользователя. Чтобы дать возможность хранить состояние между запросами (например, настройки пользователя или его данные)

Хранит данные, которые можно передавать на сервер через заголовки. Локальное и сессионное хранилище доступны только на клиентской стороне. Срок хранения устанавливается при создании cookie. Объём данных не превышает 4 Кбайт. Cookie могут быть защищёнными, в этом случае их содержимое нельзя получить на стороне клиента. Это важно для аутентификации при хранении пользовательских токенов.

//
const readCookie = document.cookie;

// сохранить в куки поле user со значением John, которое сотрется 19 Jan 2038 03:14:07 GMT
document.cookie = 'user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT';
document.cookie =
'cookieName=Cookie value; expires=Sun, 15 Jun 2019 23:59:00 UTC; path=/javascript-cheatsheet'; // Cookie with an expiry date and a path set

// с переменными, установить на год
document.cookie = `cookie_name=${cookie_value}; expires=${new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365).toGMTString()}; path=/`;
// set
Cookies.set('name', 'value');
Cookies.set('name', 'value', { expires: 7 });

// get
Cookies.get('name'); // => 'value'
Cookies.get('nothing'); // => undefined
Cookies.get(); // => { name: 'value' }

// remove
Cookies.remove('name');

Stateless​

HTTP — Stateless протокол. Он не хранит состояние клиента между запросами, всё состояние целиком описывается в каждом запросе. Про stateless management можно прочитать в RFC. Были времена, когда JavaScript не так прочно обосновался в веб-приложениях. Тогда не было никаких одностраничных приложений и сайтов, не было хранения состояния на клиенте, а каждая кнопка или ссылка создавала новый запрос к серверу, менялся URL и сервер на каждый запрос формировал новую HTML-страницу в ответ. Так, например, до сих пор работают популярные CMS, такие как WordPress или Joomla, хотя в них и можно встраивать плагины на JS. Но как же тогда сохранять состояние между запросами? Если пользователь авторизовался — эту информацию надо где-то держать, и как это сделать без JS, без клиентского состояния? Выход есть — куки.

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

Куки — это просто заголовки, но браузеры договорились, как с ними работать, и обязательно это делают. Если браузер встречает в ответе заголовки cookie — он сохраняет их к себе в память. И, соответственно, если при запросе к домену браузер видит, что у него есть куки для этого домена, — он подставит их в запрос.

Некоторые особенности куки:

  • куки ставятся на конкретный домен,
  • браузер должен хранить как минимум 4096 байт cookies,
  • имена нечувствительны к регистру.

Сервер устанавливает клиенту куки в ответе на запрос через специальный заголовок Set-Cookie: Set-Cookie: name=value. Далее браузер должен отправлять серверу куку через заголовок Cookie: Cookie: name=value. Подробнее про заголовок можно почитать на MDN.

Где применяются куки:​

  • аутентификация пользователей. Про отличие идентификации, аутентификации и авторизации можно прочитать здесь,
  • хранение настроек пользователей,
  • сессия пользователя,
  • сбор различной статистики,
  • и многое другое.
Set-Cookie: value
[; Expires=date]
[; Max-Age=age]
[; Domain=domain]
[; Path=path]
[; Secure]
[; HttpOnly]

Важные атрибуты — secure и httponly.

Атрибут httponly делает куки доступными только по HTTP-запросам. Доступ через JavaScript при этом к этим кукам запрещён — это очень важно.

В браузере из JavaScript можно получить значение куки через document.cookie. Это открывает дверь злоумышленникам, которые охотятся за пользовательскими данными. Кука может быть «паспортом» пользователя в приложении, потому желательно не допускать кражу таких данных либо делать так, чтобы кража была бесполезной. Про методы защиты будем говорить отдельно.

Атрибут httponly усложняет задачу злоумышленникам. Да и в наше время куки очень редко нужны фронтенд-разработчикам — хватает других инструментов. Клиент не должен работать с куками.

Атрибут secure говорит браузеру, что куку можно установить только при защищённом HTTPS-соединении. Если запрос приходит от HTTP, то браузер просто не поставит данную куку. Про HTTPS и SSL расскажем позднее.