Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Заголовки безопасности и ограничение запросов

Два простых шага заметно повышают защиту API. Первый — защитные заголовки ответа: они говорят браузеру, что запрещено делать с вашим сайтом. Второй — ограничение частоты запросов (rate limiting): один клиент не сможет отправить тысячи запросов в минуту, например перебирая пароли на /login.

Установка

npm install @fastify/helmet @fastify/rate-limit

Helmet

Плагин @fastify/helmet добавляет к каждому ответу набор защитных заголовков. Подключите его в src/app.js:

// src/app.js
import helmet from '@fastify/helmet';
 
app.register(helmet);

Выполните curl -i http://localhost:3000/posts — среди заголовков появятся, например, x-content-type-options: nosniff и content-security-policy.

ЗаголовокЧто запрещает
Content-Security-PolicyЗагрузку скриптов и стилей с чужих адресов
X-Content-Type-OptionsУгадывание типа файла браузером
X-Frame-OptionsВстраивание сайта в чужой iframe
Strict-Transport-SecurityОбращение к сайту без HTTPS

Для чистого JSON API настройки по умолчанию подходят. Если сервер отдаёт и HTML-страницы, политику contentSecurityPolicy настраивают под свои скрипты.

Ограничение запросов

Плагин @fastify/rate-limit считает запросы с каждого IP-адреса и после превышения лимита отвечает кодом 429 «Too Many Requests»:

// src/app.js
import rateLimit from '@fastify/rate-limit';
 
app.register(rateLimit, {
  max: 100,
  timeWindow: '1 minute',
});

Теперь с одного адреса можно сделать не больше 100 запросов в минуту. В каждом ответе есть заголовки x-ratelimit-limit и x-ratelimit-remaining — лимит и сколько запросов осталось.

Свой лимит для маршрута

Маршрут входа стоит ограничить строже. Лимит задаётся в опции config маршрута в src/routes/auth.js:

// src/routes/auth.js
app.post('/login', {
  config: {
    rateLimit: { max: 5, timeWindow: '1 minute' },
  },
}, async (request) => {
  // ...проверка логина и выдача токена
});

Шестая попытка входа за минуту получит ответ 429, и подбирать пароль станет бессмысленно.

Порядок подключения

Оба плагина подключайте в src/app.js раньше маршрутов: rate-limit применяет лимиты к маршрутам, которые объявлены после него.

Частая ошибка

За обратным прокси (например, nginx) все запросы приходят с одного адреса — адреса прокси, — и лимит срабатывает сразу для всех посетителей. Включите опцию trustProxy: true при создании приложения, чтобы Fastify брал настоящий IP клиента из заголовка X-Forwarded-For.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.