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

Безопасность Express.js: практическое руководство по защите серверных приложений

• 7 min read • Security • Обновлено 24 Nov 2025
Защита Express.js: практический гид
Защита Express.js: практический гид

Навешенный замок на фоне кода — символ безопасности сервера

Express.js — быстрый и удобный каркас для серверных Node.js‑приложений. Но по умолчанию он не обеспечивает все необходимые меры безопасности. Без продуманной защиты уязвимости (XSS, CSRF, инъекции, утечки заголовков и т.д.) могут привести к компрометации данных пользователей.

В этом материале мы подробно опишем практические шаги и шаблоны, которые вы можете применить прямо сейчас. Показано, как настроить минимальный рабочий пример, как проверять текущую конфигурацию, какие middleware подключать, а также предлагаются операционные чек‑листы и план реагирования.

Что вы получите из этой статьи

  • Пошаговая настройка простого Express.js‑сервера.
  • Инструкции по установке Helmet, Joi и CORS с примерами кода.
  • Рекомендации по дополнительным мерам: HTTPS, rate limiting, cookie‑флаги, CSP.
  • Чек‑лист перед релизом и playbook на случай инцидента.

Предположения и определения

  • Express.js — фреймворк для Node.js, используемый для создания HTTP‑серверов.
  • Middleware — функции, которые обрабатывают запрос/ответ в цепочке Express.
  • CSP — Content Security Policy, политика содержания, снижающая риск XSS.

Установка и базовый пример Express.js

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

mkdir express-project
cd express-project
npm init -y

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

npm install express

Создайте файл server.js с минимальным сервером:

const express = require("express")
const app = express()
const PORT = process.env.PORT || 5000

app.get("/", (req, res) => {
  res.json("Hello, World!")
})

app.listen(PORT, () => {
  console.log(`Starting server on http://localhost:${PORT}`)
})

Запустите сервер:

node server.js

Важно: на реальном сервисе ставьте NODE_ENV=production и используйте менеджер процессов (pm2, systemd) или контейнеры.

1. Защита заголовков HTTP с помощью Helmet

Helmet — это набор middleware для установки безопасных HTTP‑заголовков. Он защищает от ряда распространённых атак, снижая поверхность атаки.

Разработчик за ноутбуком с кодом на экране

Без специальных заголовков сервер выдает информацию, например заголовок X-Powered-By, который раскрывает технологию (Express). Удаление или замена таких заголовков затрудняет сбор информации об инфраструктуре атакующими.

Как проверить текущие заголовки

Откройте DevTools в браузере или выполните запрос через Postman. В разделе Headers вы увидите отправленные сервером поля.

Результат ответных заголовков HTTP в Postman

Обратите внимание на X-Powered-By. Рекомендуется удалить или изменить его на заглушку.

Базовая интеграция Helmet

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

npm install helmet

Подключите middleware в server.js:

const helmet = require("helmet")
app.use(helmet())

После включения Helmet повторно просканируйте заголовки. Для примерной автоматической оценки можно использовать сервис Security Headers. Если ваш сервер локальный, временно откройте его через ngrok:

ngrok http 5000

Вывод информации ngrok в терминале, показывающий forwarding URL

Вставьте forwarding URL в Security Headers и нажмите Scan.

Поле ввода forwarding URL в инструменте Security Headers

До настройки вы, возможно, увидите низкую оценку.

Отчёт Security Headers с низкой оценкой (F)

После включения Helmet часто оценивают страницу существенно выше.

Отчёт Security Headers с высокой оценкой (A)

Настройка конкретных заголовков

Helmet даёт конфигурационные опции. Примеры полезных настроек:

// Более строгий набор заголовков
app.use(helmet.hidePoweredBy()); // скрыть X-Powered-By
app.use(helmet.frameguard({ action: 'deny' })); // защита от clickjacking
app.use(helmet.xssFilter()); // X-XSS-Protection

// Настройка CSP (Content Security Policy)
const { contentSecurityPolicy } = require('helmet')
app.use(contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", 'https://trusted.cdn.example'],
    objectSrc: ["'none'"],
    upgradeInsecureRequests: [],
  }
}))

Важно: CSP требует тестирования и может сломать сторонние виджеты. Включайте поэтапно и логируйте нарушения.

2. Валидация входных данных с помощью Joi

Валидация входных данных помогает предотвратить инъекции и некорректные состояния приложения. Joi — удобная библиотека для описания схем и валидации.

Установка и базовый пример

npm install joi

Подключите и используйте Joi совместно с парсером тела запроса:

const Joi = require('joi')
app.use(express.json()) // важно: подключить до обработки роутов

const schema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(5).max(50).required()
})

app.post('/register', (req, res) => {
  const { error, value } = schema.validate(req.body)
  if (error) {
    return res.status(400).json({ error: error.details[0].message })
  }
  // безопасно работать с value
  res.status(201).json({ ok: true })
})

Рекомендации по применению Joi

  • Валидируйте на границе приложения — сразу после парсинга тела запроса.
  • Не используйте пользовательский ввод напрямую в SQL/NoSQL — применяйте параметры запросов и ORM.
  • Ограничивайте длину строк и глубину вложенных структур.

3. Контроль Cross‑Origin Resource Sharing (CORS)

CORS управляет, какие домены могут делать запросы к вашему API из браузера. Неправильная настройка CORS позволяет чужим сайтам отправлять запросы от имени пользователя.

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

npm install cors
const cors = require('cors')
// Строгая политика: разрешить только конкретный домен
app.use(cors({ origin: 'https://app.example.com' }))

// Для нескольких доменов
const whitelist = ['https://app.example.com', 'https://admin.example.com']
app.use(cors({
  origin: function(origin, callback){
    if (!origin) return callback(null, true) // allow non-browser clients
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}))

Важно: app.use(cors()) по умолчанию открывает доступ всем; это безопасно только для публичных API без авторизации.

Дополнительные меры защиты (с практическими примерами)

Ниже перечислены дополнительные подходы, которые усиливают защиту в комбинации с Helmet, Joi и CORS.

TLS/HTTPS

Всегда используйте HTTPS в продакшене. На этапе разработки можно тестировать с самоподписанными сертификатами, но в продакшене устанавливайте сертификаты от доверенных центров (Let’s Encrypt). Размещайте TLS на уровне балансировщика или reverse proxy (nginx, Cloudflare), а не только в Node.js.

Защита сессий и cookie

Если вы используете cookie для сессий, выставляйте флаги Secure и HttpOnly и по возможности SameSite:

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax'
  }
}))

Rate limiting (ограничение частоты запросов)

Чтобы защититься от brute force и DoS, используйте express-rate-limit:

npm install express-rate-limit
const rateLimit = require('express-rate-limit')
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 минут
  max: 100 // максимальное число запросов с одного IP
})
app.use('/api/', apiLimiter)

Логирование и мониторинг

Ведите аудиторные логи успешных и неуспешных попыток входа, изменения прав и критичных ошибок. Используйте централизованные системы (ELK, Graylog, Datadog), чтобы иметь возможность кореллировать события.

Проверки на стороне базы данных

Используйте параметризованные запросы и ORM/ODM вместо конкатенации строк. Проверяйте ограничения на уровне СУБД (уникальные индексы, foreign key, ограничения целостности).

Тестирование безопасности и инструменты аудита

  • Static Application Security Testing (SAST): анализ кода на уязвимости.
  • Dynamic Application Security Testing (DAST): сканеры, имитирующие атаки.
  • Dependency scanning: проверка уязвимостей в npm‑пакетах (npm audit, Snyk, Dependabot).

Запуск npm audit и исправление известных уязвимостей — обязательная часть CI.

Чек‑лист перед релизом

  • NODE_ENV=production
  • Helmet включён и настроен
  • CSP протестирована и не ломает приложение
  • Joi (или другая валидация) покрывает все публичные эндпоинты
  • CORS ограничен до необходимых доменов
  • HTTPS настроен и сертификаты валидны
  • Cookie flags выставлены (Secure, HttpOnly, SameSite)
  • Rate limiting включён на критичных маршрутах
  • Логирование ошибок и аутентификации работает
  • Зависимости обновлены и проверены на уязвимости

План реагирования на инцидент (простая версия)

  1. Идентификация: зафиксируйте начало инцидента и симптомы.
  2. Изоляция: при необходимости временно ограничьте доступ (rate limit, отключение функций).
  3. Сбор данных: снимки логов, стек трейс, входящие запросы, IP.
  4. Оценка воздействия: какие данные или сервисы затронуты.
  5. Устранение: откат конфигурации, патч, фильтрация трафика.
  6. Восстановление: вернуть сервис в рабочее состояние по шагам.
  7. Анализ и уроки: провести RCA (root cause analysis) и обновить чек‑листы.

Важно: заранее подготовьте ролевая матрица — кто отвечает за коммуникации, кто за форензик‑логи, кто за фиксы.

Частые ошибки и случаи, когда подходы не работают

  • Открыть CORS для всех, а затем удивляться утечкам: публичный доступ и авторизация — разные вещи.
  • Включить CSP слишком жёстко без лога нарушений — сторонние скрипты перестанут работать.
  • Полагаться только на Helmet и считать систему защищённой — это базовый уровень, а не полная защита.
  • Не валидировать входящие данные между внутренними сервисами — межсервисная коммуникация тоже должна быть валидной.

Ролевые чек‑листы (кто за что отвечает)

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

    • Включить и настроить Helmet и CORS.
    • Добавить Joi/валидацию на каждый эндпоинт.
    • Обработать ошибки и не раскрывать стеки в ответах.
  • DevOps

    • Настроить TLS и автоматическое обновление сертификатов.
    • Развернуть обратный прокси (nginx) с rate limiting и базовой защитой.
    • Настроить мониторинг и алерты.
  • Безопасность/QA

    • Проводить SAST/DAST перед релизом.
    • Проводить аудит зависимостей.
    • Тестировать CSP и заголовки.

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

  • Все публичные эндпоинты возвращают корректные коды ошибок, без утечки внутренних сообщений.
  • Для типовых атак (XSS, SQL/NoSQL‑инъекции) есть позитивные и негативные тесты, проходящие в CI.
  • Security Headers не менее уровня B по внутреннему рейтингу (или A для критичных сервисов).

Шаблоны и сниппеты

Мини‑шаблон server.js с рекомендованными middleware:

const express = require('express')
const helmet = require('helmet')
const cors = require('cors')
const rateLimit = require('express-rate-limit')
const Joi = require('joi')

const app = express()
app.use(express.json())
app.use(helmet())
app.use(cors({ origin: 'https://app.example.com' }))
app.use(rateLimit({ windowMs: 15*60*1000, max: 100 }))

// Пример роутера с валидацией
const loginSchema = Joi.object({ username: Joi.string().required(), password: Joi.string().required() })
app.post('/login', (req, res) => {
  const { error, value } = loginSchema.validate(req.body)
  if (error) return res.status(400).json({ error: error.details[0].message })
  // аутентификация...
  res.json({ ok: true })
})

app.use((err, req, res, next) => {
  console.error(err)
  res.status(500).json({ error: 'Internal Server Error' })
})

app.listen(process.env.PORT || 5000)

Короткое руководство по миграции существующего проекта

  1. Создайте ветку и добавьте helmet, cors и rate limiter в dev‑сборку.
  2. Примените валидацию ко всем публичным роутам по одному.
  3. Запустите интеграционные тесты и DAST.
  4. Постепенно включайте CSP: сначала в режиме report‑only, затем включайте enforcement.
  5. После успешного тестирования разверните на staging, затем на production.

Заключение

Защита Express.js‑приложений достигается комбинацией мер: правильные HTTP‑заголовки (Helmet), строгая валидация входных данных (Joi), контроль происхождения запросов (CORS), защита на уровне транспортного уровня (HTTPS), ограничение частоты запросов и надёжная конфигурация cookie и сессий. Это не одноразовая задача — безопасность нужно поддерживать в CI/CD, тестировать и обновлять зависимости.

Важно: начните с базовых мер (Helmet, Joi, CORS), затем постепенно добавляйте мониторинг, rate limiting и CSP. Проводите регулярные аудиты и готовьте план реагирования на инциденты.

Важно: ни одна мера не даёт стопроцентной гарантии. Ставьте защиту уровнями и регулярно проверяйте её эффективность.

Ключевые ссылки и ресурсы

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

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

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро