Гид по технологиям

Аутентификация в Node.js + PostgreSQL с Passport.js

6 min read Аутентификация Обновлено 09 Jan 2026
Аутентификация Node + PostgreSQL с Passport.js
Аутентификация Node + PostgreSQL с Passport.js

Крупный план клавиш клавиатуры

Как разработчик, вы отвечаете за защиту данных пользователей через корректную аутентификацию. Passport.js помогает управлять проверкой подлинности в приложении Node + PostgreSQL и снижает количество повторяющегося кода при реализации логина и регистрации.

Что вы получите

  • Рабочий набор файлов и маршрутов для регистрации и входа пользователя.
  • Безопасное хранение паролей с bcrypt.
  • Примеры вспомогательных функций для работы с БД и их тестирования.
  • Практические советы по безопасности и развертыванию.

Важно: пример ориентирован на учебные и начальные продакшен-решения. Перед выводом в продакшен применяйте дополнительные меры безопасности (TLS, переменные окружения, ограничение прав БД и т. п.).

Создание таблицы users

Для аутентификации понадобятся поля email и password. В psql создайте базу данных nodeapp:

CREATE DATABASE nodeapp;  

Далее создайте таблицу пользователей:

CREATE TABLE users (  
 id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,  
 email CHAR(128),  
 password CHAR(60)  
);  

Этот код создаст таблицу с полями email, password и автоинкрементным id. Примечание: в реальной системе имеет смысл использовать типы VARCHAR и уникальный индекс на email, например “email VARCHAR(255) UNIQUE”.

Создание Node-сервера

Node.js — это серверная среда для запуска JavaScript. Для простоты создаём сервер на Express.

Создайте папку и инициализируйте проект:

mkdir postgres-auth  
npm init -y  

Установите Express:

npm install express  

Создайте файл index.js и добавьте:

const express = require("express");  
const app = express();  
app.use(express.json());  
app.use(express.urlencoded({ extended: true }));  
app.listen(3000, () => console.log("Listening on port 3000"));  

Запуск этого кода стартует сервер и выведет в консоль:

Listening on port 3000

Совет: при разработке используйте nodemon для авто-перезапуска: npm install –save-dev nodemon.

Подключение к PostgreSQL

Для работы с PostgreSQL используем node-postgres (pg).

Установите драйвер:

npm install pg  

Создайте файл db.js и подключите клиента:

const { Client } = require("pg");  
const { user, host, database, password, port } = require("./dbConfig");  
  
const client = new Client({  
  user,  
  host,  
  database,  
  password,  
  port,  
});  
  
client.connect();  
  
module.exports = client;  

Файл dbConfig.js хранит параметры подключения (в продакшене используйте переменные окружения или менеджер секретов):

module.exports = {  
  user: "postgres",  
  host: "localhost",  
  database: "nodeapp",  
  password: "yourPassword",  
  port: 5432,  
};  

Важно: не храните пароли и секреты в коде. Используйте .env и библиотеку dotenv для локальной разработки.

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

Разделение логики работы с БД на функции упрощает тестирование и поддержку. Для регистрации нам понадобятся функции:

  1. Проверка существования email.
  2. Создание пользователя.

Создайте helper.js и импортируйте клиент из db.js:

const client = require("./db.js")  

Добавьте функцию emailExists():

const emailExists = async (email) => {  
  const data = await client.query("SELECT * FROM users WHERE email=$1", [  
    email,  
  ]);  
  
  if (data.rowCount == 0) return false;   
  return data.rows[0];  
};  

Эта функция возвращает false, если email не найден, иначе — объект пользователя.

Добавим createUser():

const createUser = async (email, password) => {  
  const salt = await bcrypt.genSalt(10);  
  const hash = await bcrypt.hash(password, salt);  
  
  const data = await client.query(  
    "INSERT INTO users(email, password) VALUES ($1, $2) RETURNING id, email, password",  
    [email, hash]  
  );  
  
  if (data.rowCount == 0) return false;  
  return data.rows[0];  
};  

Здесь пароль хешируется перед сохранением. Не храните пароли в открытом виде.

Установите bcryptjs:

npm install bcryptjs  

Импортируйте bcryptjs в helper.js:

const bcrypt = require("bcryptjs")  

Добавьте matchPassword() для сравнения пароля при входе:

const matchPassword = async (password, hashPassword) => {  
  const match = await bcrypt.compare(password, hashPassword);  
  return match  
};  

Экспортируйте функции:

module.exports = { emailExists, createUser, matchPassword };  

Совет по безопасности: используйте VARCHAR вместо CHAR для паролей и email. CHAR фиксирует длину и приводит к пробелам на конце.

Настройка Passport

Passport — middleware для Node, поддерживающий множество стратегий аутентификации. Для локальной аутентификации используем passport-local.

Установите Passport и стратегию:

npm install passport  
npm install passport-local  

Создайте файл passportConfig.js и импортируйте LocalStrategy и функции из helper.js:

const LocalStrategy = require("passport-local");  
const { emailExists, createUser, matchPassword } = require("./helper");  

Добавьте стратегию для регистрации:

module.exports = (passport) => {  
  passport.use(  
    "local-signup",  
    new LocalStrategy(  
      {  
        usernameField: "email",  
        passwordField: "password",  
      },  
      async (email, password, done) => {  
        try {  
          const userExists = await emailExists(email)  
  
          if (userExists) {  
            return done(null, false);  
          }  
  
          const user = await createUser(email, password);  
          return done(null, user);  
        } catch (error) {  
          done(error);  
        }  
      }  
    )  
  );  
}  

Passport ожидает поля username и password, поэтому мы указываем usernameField: “email”.

Добавим стратегию для логина:

module.exports = (passport) => {  
  passport.use(  
    "local-signup",  
    new LocalStrategy(  
// sign up  
    )  
  );  
  passport.use(  
    "local-login",  
    new LocalStrategy(  
      {  
        usernameField: "email",  
        passwordField: "password",  
      },  
      async (email, password, done) => {  
        try {  
          const user = await emailExists(email);  
          if (!user) return done(null, false);  
          const isMatch = await matchPassword(password, user.password);  
          if (!isMatch) return done(null, false);  
          return done(null, {id: user.id, email: user.email});  
        } catch (error) {  
          return done(error, false);  
        }  
      }  
    )  
  );  
};  

Стратегия для входа ищет пользователя по email и проверяет пароль через matchPassword().

Создание маршрутов API

Окончательно создадим маршруты для регистрации и входа:

Импортируем и настраиваем Passport в файле server.js (или index.js):

const passport = require("passport");  
require("./passportConfig")(passport);  

Добавьте маршруты:

app.post(  
  "/auth/signup",  
  passport.authenticate("local-signup", { session: false }),  
  (req, res, next) => {  
    res.json({  
      user: req.user,  
    });  
  }  
);  
  
app.post(  
  "/auth/login",  
  passport.authenticate("local-login", { session: false }),  
  (req, res, next) => {  
    res.json({ user: req.user });  
  }  
);  

Обе конечные точки возвращают JSON с объектом user при успешной аутентификации.

Примечание: здесь session: false — это вариант без сессий. Для использования сессий добавьте express-session и реализуйте serializeUser/deserializeUser.

Тестирование API и юнит-тесты

Тесты упрощают поиск ошибок на ранних этапах. Для Node-приложений часто используют Jest и supertest для интеграционных тестов маршрутов.

Минимальные сценарии тестирования:

  • Успешная регистрация нового пользователя.
  • Ошибка при попытке зарегистрировать уже существующий email.
  • Успешный вход корректным email+паролем.
  • Ошибка входа при неверном пароле.
  • Валидация формата email и длины пароля.

Пример тест-кейса (псевдокод, не полный файл):

// using supertest + jest
it('should register a new user', async () => { 
  const res = await request(app)
    .post('/auth/signup')
    .send({ email: 'test@example.com', password: 'pass1234' });
  expect(res.statusCode).toBe(200);
  expect(res.body.user).toHaveProperty('id');
});

Рекомендации по безопасности и жёсткая настройка

Важно: аутентификация — критический компонент. Ниже базовый чек-лист жёсткой настройки:

  • Храните секреты в переменных окружения (process.env) или менеджере секретов.
  • Используйте HTTPS (TLS) для всех клиентских запросов.
  • Устанавливайте и обновляйте зависимости (npm audit, Dependabot).
  • Ограничивайте права пользователя БД: предоставляйте только нужные разрешения (SELECT, INSERT для таблицы users).
  • Включите защиту от перебора паролей: rate limiting, account lockout, CAPTCHA при попытках входа.
  • Подтверждение email при регистрации и сброс пароля через одноразовые токены.
  • Храните пароли с современными параметрами: bcrypt с salt rounds >= 10 (регулируйте по мощности сервера).
  • Защита заголовков: helmet middleware.
  • CSRF: применимо для cookie-based аутентификации.
  • Валидация входных данных: проверяйте формат email, минимальную длину и символы пароля.
  • Логи: логируйте попытки входа, но не храните пароли в логах.
  • Подключение к БД по TLS, если БД находится на удалённом хосте.

Примеры полезных пакетов:

npm install dotenv helmet express-rate-limit

Пример использования helmet и rate limit в Express:

const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
app.use(helmet());
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));

Альтернативные подходы

  • JWT (JSON Web Tokens): альтернатива сессиям. Хорош для stateless API. Храните refresh-токены безопасно.
  • OAuth / социальная аутентификация: passport поддерживает множество внешних провайдеров.
  • Использование готовых сервисов (Auth0, Firebase Auth) для уменьшения операционной нагрузки.

Когда локальная стратегия passport-local подходит: простые приложения и внутренняя аутентификация. Когда не подходит: когда нужно масштабировать распределённую систему с безгосударственными сервисами и короткими токенами — чаще выбирают JWT.

Методология внедрения (мини-план)

  1. Разработать схему БД и гарантировать уникальность email.
  2. Настроить локальную среду и .env.
  3. Реализовать helper-функции и покрыть их юнит-тестами.
  4. Подключить Passport, добавить стратегии signup/login.
  5. Добавить middleware безопасности (helmet, rate limiter).
  6. Написать интеграционные тесты для маршрутов.
  7. Настроить CI, автоматические тесты и проверку зависимостей.
  8. Развернуть на staging, прогнать нагрузочное тестирование и тесты безопасности.
  9. Перейти в продакшен с мониторингом и алертами.

Риски и меры смягчения

  • Риск: утечка секретов. Мера: убрать секреты из репозитория, использовать vault.
  • Риск: перебор пароля. Мера: rate limiting, блокировки, мониторинг.
  • Риск: SQL-инъекции. Мера: используйте параметризированные запросы (пример выше использует $1).
  • Риск: слабые пароли. Мера: требовать минимальную длину и проверять по списку общих паролей.

Роли и чек-листы

Разработчик:

  • Написать helper-функции и покрыть тестами.
  • Добавить обработку ошибок.
  • Проверить валидацию входных данных.

DevOps:

  • Настроить переменные окружения и секреты.
  • Убедиться в TLS между клиентом и сервером.
  • Ограничить права БД.

QA:

  • Написать тест-кейсы для регистрации и логина.
  • Проверить обработку ошибок и кейсы краёв.

Security:

  • Провести ревью зависимостей.
  • Протестировать на уязвимости (SAST/DAST).

Критерии приёмки

  • Регистрация возвращает объект user с id и email.
  • Попытка регистрации с существующим email возвращает ошибку/статус 4xx.
  • Успешный вход возвращает user без пароля.
  • Никакой пароль не логируется и не возвращается клиенту.
  • Тесты на основные сценарии проходят в CI.

Глоссарий (одна строка, определения)

  • Passport: middleware для Node.js, реализующий стратегии аутентификации.
  • passport-local: стратегия Passport для логина по username/password.
  • bcrypt: алгоритм для хеширования паролей с солью.
  • JWT: JSON Web Token, формат токенов для stateless-аутентификации.

Шпаргалка команд и конфигурация

.env (пример):

DB_USER=postgres
DB_HOST=localhost
DB_NAME=nodeapp
DB_PASS=yourPassword
DB_PORT=5432
PORT=3000

Полезные команды:

npm install express pg passport passport-local bcryptjs dotenv helmet express-rate-limit
npm install --save-dev jest supertest nodemon

Примеры отказов и когда подход не подходит

  • Если ваше приложение требует single-sign-on (SSO) для корпоративной среды, используйте OAuth2/OpenID Connect.
  • Для распределённых микросервисов с масштабируемым безгосударственным доступом JWT чаще подходит лучше, чем сессии.

Короткое резюме

  • Passport.js с passport-local позволяет быстро добавить локальную аутентификацию в Node + PostgreSQL.
  • Хешируйте пароли с bcrypt и храните секреты вне кода.
  • Добавьте rate limiting, helmet и валидацию для повышения безопасности.

Важно: перед запуском в продакшен поставьте дополнительные уровни защиты и тестирование.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство