В информатике, а конкретно в сетях, сессия — это интерактивный обмен информацией, также известный как диалог между двумя или более общающимися устройствами, или между компьютером и пользователем. Сессия (cеанс) устанавливается в определённый момент времени и позже завершается.
HTTP session
Так как HTTP — это клиент-серверный протокол, HTTP сессия состоит из трёх фаз:
- Клиент устанавливает TCP соединение (или другое соединение, если не используется TCP транспорт).
- Клиент отправляет запрос и ждёт ответа.
- Сервер обрабатывает запрос и посылает ответ, в котором содержится код статуса и соответствующие данные.
Начиная с версии HTTP/1.1, после третьей фазы соединение не закрывается, так как клиенту позволяется инициировать другой запрос. То есть, вторая и третья фазы могут повторяться.
User session
Пользовательская сессия является более высокоуровневой абстракцией, чем HTTP-сессия. С помощью неё можно не только идентифицировать разных пользователей, но также хранить произвольные данные на каждого пользователя в рамках его сессии. Типичный пример - это корзина товаров в интернет-магазине. Обратите внимание на то, что для пользовательской сессии не обязательно логиниться (выполнять аутентификацию) на сайте.
Поддержка сессий обычно реализуется с помощью специальных библиотек в рамках используемого фреймворка. В задачи этих библиотек входит:
- Установка соединения, то есть отправка специальной куки, которая содержит идентификатор сессии. Имя этой куки фиксированно и задаётся на этапе старта приложения.
- Сохранение и извлечение данных из сессии. Этот пункт сильно зависит от используемого фреймворка. В случае Express предоставляется специальный объект
req.session
, в который можно записывать необходимую информацию и читать её в следующих запросах. Отдельный интерес представляет хранилище данных сессии. Это можно делать в памяти, прямо в куках (в зашифрованном виде), или в различных серверных хранилищах начиная от файлов, заканчивая базами данных. - Завершение сессии.
import session from 'express-session';
app.use(session({
resave: false,
saveUninitialized: false,
}));
У библиотеки express-session
очень много параметров, влияющих на работу сессии, и большое количество дополнений, позволяющих использовать различные хранилища. За подробностями обращайтесь к официальной документации.
К счастью, использовать сессии гораздо проще, чем их настраивать.
app.get('/increment', (req, res) => {
req.session.counter = req.session.counter || 0;
req.session.counter += 1;
});
В примере выше в сессии инициализируется свойство counter
значением 0
, а затем, при каждом обновлении страницы, счётчик увеличивается на единицу. Это будет происходить для каждого браузера независимо, потому что кука устанавливается в браузер, и браузер является "пользователем".
Для удаления сессии нужно вызывать асинхронный метод destroy
.
req.session.destroy((err) => {
// cannot access session here
})
Аутентификация
Аутентификация это процедура проверки подлинности, например:
- Проверка подлинности пользователя путём сравнения введённого им пароля с паролем, сохранённым в базе данных пользователей;
- Подтверждение подлинности электронного письма путём проверки цифровой подписи письма по открытому ключу отправителя;
- Проверка контрольной суммы файла на соответствие сумме, заявленной автором этого файла.
Аутентификацию не следует путать с авторизацией (процедурой предоставления субъекту определённых прав) и идентификацией (процедурой распознавания субъекта по его идентификатору).
Вот как может выглядеть процесс аутентификации в Express:
app.post('/session', (req, res) => {
// ...
if (user.passwordDigest === encrypt(password)) {
req.session.userId = user.id;
// ...
}
// ...
});
При совпадении паролей в сессию устанавливается идентификатор пользователя под ключом, который потом будет использоваться для проверки, аутентифицирован ли пользователь.
Обратите внимание на то, что в примере выше используется не сам пароль, а его хешированная версия. С точки зрения безопасности ни в коем случае нельзя хранить пароли в открытом виде. Поэтому при создании пользователя пароль специальным образом хешируется, и в хранилище уже сохраняется этот хеш. Во время процедуры аутентификации пароль, вводимый пользователем, хешируется тем же способом, что и при регистрации, а затем происходит сравнение хешей.
// encrypt.js
import crypto from 'crypto';
export default text => {
const hash = crypto.createHmac('sha512', 'salt');
hash.update(text);
return hash.digest('hex');
};
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты