Погружение в мир управления сессиями

HTTP и HTTPS — это интернет-протоколы, которые позволяют отправлять данные через Интернет путем отправки запроса через веб-браузер. Поскольку они не имеют состояния, каждый запрос, отправленный в браузер, обрабатывается независимо. Это означает, что браузер не может запомнить источник запроса, даже если его делает тот же пользователь. Сеансы HTTP решают эту проблему.

В этой статье мы рассмотрим управление сеансами и то, как такие инструменты, как Passport, Redis и MySQL, могут помочь нам управлять сеансами Node.js. Давайте углубимся.

Как работают HTTP-сессии?

Сеансы HTTP позволяют веб-серверам сохранять удостоверение пользователя и хранить пользовательские данные при множественных взаимодействиях типа запрос/ответ между клиентским приложением и веб-приложением. Когда клиент входит в приложение, сервер генерирует SessionID. Сеанс сохраняется в памяти с использованием односерверного механизма постоянного хранения без репликации. Примеры таких механизмов включают сохранение JDBC, сохранение файловой системы, сохранение сеанса на основе файлов cookie и репликацию в памяти.

Когда пользователь отправляет последующий запрос, в заголовке запроса передается sessionID, и браузер проверяет, совпадает ли идентификатор с каким-либо идентификатором в памяти, и предоставляет пользователю доступ до истечения срока действия сеанса.

Сеансы HTTP хранят в памяти следующие данные:

  • Особенности сеанса (идентификатор сеанса, время создания, время последнего доступа и т. д.)
  • Контекстная информация о пользователе (например, статус входа клиента)

Что такое Редис?

Redis (Remote Dictionary Server) — это быстрое хранилище данных типа «ключ-значение» с открытым исходным кодом в памяти, используемое в качестве базы данных, кэша, брокера сообщений и очереди.

Время отклика Redis составляет менее миллисекунды, что позволяет обрабатывать миллионы запросов в секунду для приложений реального времени в таких отраслях, как игры, рекламные технологии, финансы, здравоохранение и IoT. В результате Redis теперь является одним из самых популярных движков с открытым исходным кодом, который пять лет подряд был назван «Самой любимой» базой данных Stack Overflow.

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

Что мы строим?

Чтобы продемонстрировать управление сеансами в Node.js, мы создадим простое приложение для регистрации и входа. Пользователи будут регистрироваться и входить в это приложение, указав свой адрес электронной почты и пароль. Сеанс создается и сохраняется в хранилище Redis для будущих запросов, когда пользователь входит в систему. Когда пользователь выходит из системы, мы удаляем его сеанс. Хватит болтать. Давайте начнем!

Предпосылки

Этот урок представляет собой практическую демонстрацию. Перед началом работы убедитесь, что у вас установлено следующее:

Код для этого руководства доступен в моем репозитории на GitHub. Почувствуйте клонирование и следуйте за ним.

Настройка проекта

Начнем с создания папки проекта для приложения с помощью следующей команды:

mkdir Session_management && cd Session_management

Затем инициализируйте приложение Node.js для создания файла package.json с помощью следующей команды:

npm init -y

Флаг -y в приведенной выше команде указывает npm использовать конфигурацию по умолчанию. Теперь создайте следующую структуру папок в корневом каталоге вашего проекта.

Создав наш package.json, давайте установим необходимый пакет для этого проекта в следующем разделе.

Установка зависимостей

Мы установим следующие зависимости для нашего приложения:

  • Bcryptjs — Этот модуль будет использоваться для хеширования пароля пользователя.
  • Connect-redis — Этот модуль предоставит хранилище сеансов Redis для Express.
  • Express-session — Этот модуль будет использоваться для создания сессий.
  • Ejs — Этот модуль является нашим шаблонизатором
  • Passport — Этот модуль будет использоваться для аутентификации пользователя
  • Passport-local — этот модуль будет использоваться для локальной аутентификации по имени пользователя и паролю.
  • Sequelize — Этот модуль является нашим MySQL ORM для подключения нашего приложения к базе данных MySQL.
  • Dotenv — Этот модуль будет использоваться для загрузки наших переменных окружения.

Используйте команду ниже, чтобы установить все необходимые зависимости.

npm install bcryptjs connect-redis redis express-session ejs passport passport-local sequelize dotenv

Дождитесь окончания установки. После завершения установки перейдите к настройке базы данных MySQL в следующем разделе.

Настройка базы данных MySQL

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

CREATE USER 'newuser'@'localhost' IDENTIFIED BY '1234';

Теперь создайте базу данных session_db и предоставьте newuser доступ к базе данных с помощью следующей команды:

#Create database
CREATE DATABASE session_db; 

 #grant access
GRANT ALL PRIVILEGES ON session_db TO 'newuser'@'localhost';

ALTER USER 'newuser'@'localhost' IDENTIFIED WITH mysql_native_password BY '1234';

Теперь перезагрузите все привилегии с помощью команды ниже:

FLUSH PRIVILEGES;

С нашей настройкой базы данных MySQL давайте создадим нашу модель базы данных users в следующем разделе.

Создать экспресс-сервер

С нашей настройкой базы данных MySQL давайте создадим экспресс-сервер для нашего приложения. Откройте файл src/server.js и добавьте приведенный ниже фрагмент кода:

В приведенном выше фрагменте кода мы создаем экспресс-сервер, который будет прослушивать запросы на порту 4300. Затем мы анализируем входящие запросы с полезными данными JSON, используя промежуточное ПО express.json(), и анализируем входящие запросы с помощью urlencoded, используя промежуточное ПО Express.urlencoded().

Создайте модель базы данных

На данный момент наш сервер Express настроен. Теперь мы создадим модель Users для представления пользовательских данных, которые мы увидим в базе данных, используя Sequelize. Откройте файл src/models/index.js и добавьте приведенный ниже фрагмент кода:

В приведенном выше фрагменте кода мы импортируем Sequelize и DateTypes из sequelize для подключения к нашей базе данных MySQL и назначаем тип данных свойствам нашей модели. Затем мы подключаемся к MySQL, создавая экземпляр sequelize из класса Sequelize и передавая учетные данные нашей базы данных. Например, с экземпляром sequelize мы определили нашу модель и ее свойства. Нам нужны только поля идентификатора, электронной почты и пароля этого руководства. Но sequenceize создает два дополнительных поля, поля createdAt и updatedAt.

Настройка паспорта и Redis

Для обработки и хранения учетных данных нашего пользователя мы будем использовать и настраивать Redis. Для этого откройте файл src/index.js и импортируйте следующие зависимости ниже:

const session = require("express-session");
const connectRedis = require("connect-redis");
const dotenv = require("dotenv").config()
const { createClient } = require("redis");
const passport = require("passport");

Затем найдите область с комментарием //Redis configurations и добавьте приведенный ниже фрагмент кода:

const redisClient = createClient({ legacyMode: true });
redisClient.connect().catch(console.error);
const RedisStore = connectRedis(session);

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

Затем найдите область с комментарием //Commented session middleware и добавьте приведенный ниже фрагмент кода:

В приведенном выше фрагменте кода мы создали переменную SESSION_SECRET в файле .env для хранения секрета нашего сеанса, затем создали промежуточное программное обеспечение сеанса и использовали Redis в качестве нашего хранилища. Чтобы сеанс работал, мы добавляем еще два промежуточных ПО: passport.initialize() и passport.session().

Создание контроллеров приложений

С нашей настройкой Redis и экспресс-сеанса мы создадим маршрут для обработки информации пользователей. Для этого откройте файл src/controllers/index.js и добавьте приведенный ниже фрагмент кода:

В приведенном выше фрагменте кода мы импортируем bcrypt и нашу модель User, мы деструктурируем пользовательские email и password из объекта req.body. Затем мы хэшируем пароль с помощью bcrypt и создаем нового пользователя с помощью метода sequelize create.

Затем создайте home page, registration page, login page с помощью приведенного ниже фрагмента кода:

В HomePage мы отобразим некоторые детали аутентифицированного пользователя вместе с представлением home.

Наконец, создайте маршрут logout, чтобы удалить данные имени пользователя с помощью приведенного ниже фрагмента кода:

exports.Logout = (req, res) => {
 req.session.destroy((err) => {
   if (err) {
     return console.log(err);
   }
   res.redirect("/");
 });
};

Создайте стратегию паспорта

На этом этапе пользователи могут зарегистрироваться, войти и выйти из нашего приложения. Теперь давайте создадим стратегию паспорта для аутентификации пользователей и создания сеанса. Для этого откройте файл src/utils/passport.js и добавьте приведенный ниже фрагмент кода:

В приведенном выше фрагменте кода мы импортируем passport, bcrypt и нашу модель пользователя, а также создаем промежуточное программное обеспечение паспорта для использования local-strategy. Затем мы переименовываем имя файла по умолчанию в имена полей ( email , password ), которые мы используем для аутентификации пользователей. Теперь мы проверяем, существуют ли данные пользователя в базе данных, прежде чем для них можно будет создать сеанс.

Команды Passport.serialize и passport.deserialize используются для сохранения идентификатора пользователя в виде файла cookie в браузере пользователя и для извлечения идентификатора из файла cookie при необходимости, который затем используется для получения информации о пользователе в обратном вызове.

Функция done() — это внутренняя функция passport.js, которая принимает идентификатор пользователя в качестве второго параметра.

Создайте маршруты приложений

Создав нашу стратегию паспортов, давайте приступим к созданию маршрутов для наших контроллеров. Для этого откройте файл src/routes/index.js и добавьте следующий фрагмент кода ниже:

В приведенном выше фрагменте кода мы импортируем наши функции контроллера и создаем для них маршрут. Для signin routeмы использовали метод passport.authenticate для аутентификации пользователей, используя стратегию local при настройке в предыдущем разделе.

Теперь вернемся к нашему файлу server.js. Мы создадим промежуточное ПО для наших маршрутов. Перед этим нам нужно импортировать нашу router и функцию passportConfig.

const router = require("./routes");
const { passportConfig } = require("./utils/passport");

Затем мы вызовем функцию passportConfig прямо под кодом в областях с комментариями //Configure session middleware.

passportConfig();

Затем мы создадим наше промежуточное ПО маршрута сразу после области с комментариями //Router middleware.

app.use(router);

Создадим представления нашего приложения

Создав наши маршруты, мы создадим представления, отображаемые в наших контроллерах HomePage, LoginPage и RegisterPage. Перед этим мы настроим наш движок просмотра ejs в файле server.js с фрагментом кода ниже прямо под областью с комментарием //app middleware.

app.set("view engine", "ejs");

Затем мы начнем с домашней страницы, откроем файл views/home.ejs и добавим следующую разметку:

Здесь, на нашей домашней странице, мы использовали начальную загрузку, чтобы добавить некоторые стили к нашей разметке. Затем мы проверяем, аутентифицирован ли пользователь, чтобы показать кнопку выхода. Кроме того, мы отображаем Email, sessionID и ExpirationTime пользователя из бэкенда.

Затем откройте src/views/auth/resgister и добавьте следующую разметку ниже для страницы регистрации:

На странице регистрации мы создали HTML-форму для принятия данных пользователя. В форму также добавляем атрибут active и указываем конечную точку регистрации. Это означает, что когда пользователь нажимает кнопку отправки, запрос будет отправлен на конечную точку /api/v1/signup.

Наконец, откройте файл src/views/auth/signin.js и добавьте следующий фрагмент разметки ниже:

В приведенной выше разметке мы добавили HTML-форму, которая будет использоваться для входа пользователя в систему путем отправки запроса на конечную точку /api/v1/signin.

Просмотр данных пользователей с помощью Arctype

Теперь мы успешно создали приложение для управления сеансом Node.js. Давайте посмотрим на данные пользователей с помощью Arctype. Для начала запустите Arctype, перейдите на вкладку MySQL и введите следующие учетные данные MySQL, как показано на снимке экрана ниже:

Затем щелкните таблицу users, чтобы отобразить зарегистрированных пользователей, как показано на снимке экрана ниже:

Заключение

Создав демонстрационное приложение для входа в систему, мы узнали, как реализовать управление сеансами в Node.js с помощью Passport и Redis. Мы начали с введения HTTP-сессий и того, как они работают, затем посмотрели, что такое Redis, и создали проект, чтобы применить все это на практике.

Теперь, когда у вас есть необходимые знания, как бы вы аутентифицировали проекты пользователей?