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
Фрагмент данных, отправленный веб-сервером и хранимый на компьютере пользователя. Чтобы дать возможность хранить состояние между запросами (например, настройки пользователя или его данные)
Хранит данные, которые можно передавать на сервер через заголовки. Локальное и сессионное хранилище доступны только на клиентской стороне. Срок хранения устанавливается при создании 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
:
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 расскажем позднее.