Основы Spring Security: от базовой защиты до JWT

Изучите главный фреймворк для защиты Java-приложений. Курс охватывает архитектуру Spring Security, настройку аутентификации и авторизации, работу с базой данных и реализацию JWT-токенов.

1. Введение в Spring Security и архитектура цепочки фильтров

Введение в Spring Security и архитектура цепочки фильтров

Современные веб-приложения ежедневно обрабатывают колоссальные объемы конфиденциальных данных: от личной переписки до финансовых транзакций. Защита этих данных — приоритетная задача любого разработчика. В экосистеме Java стандартом де-факто для обеспечения безопасности является Spring Security. Это мощный и гибкий фреймворк, который предоставляет комплексные механизмы для защиты корпоративных приложений.

Фундамент любой системы безопасности строится на двух базовых понятиях, которые часто путают, но их строгое разделение критически важно для понимания работы фреймворка.

Аутентификация (Authentication) — это процесс проверки подлинности пользователя. Система задает вопрос: «Ты действительно тот, за кого себя выдаешь?». Чаще всего это реализуется через проверку связки логина и пароля, но также может включать биометрию, одноразовые коды или токены.

Авторизация (Authorization) — это процесс проверки прав доступа. После того как система узнала пользователя, она задает вопрос: «Есть ли у тебя право выполнить это действие?».

Представим корпоративный портал компании, в которой работает 5 000 сотрудников. Процесс входа по корпоративному email и паролю — это аутентификация. Из этих 5 000 человек только 15 имеют должность системного администратора. Когда один из администраторов пытается удалить учетную запись уволенного сотрудника, система проверяет его роль — это авторизация. Если обычный менеджер попытается сделать то же самое, авторизация будет отклонена, несмотря на успешную аутентификацию.

> Уязвимость в безопасности = прямые убытки, утечки и репутационный удар. > > Habr: Spring Security для начинающих

Помимо базовой проверки прав, фреймворк берет на себя защиту от множества распространенных веб-уязвимостей. К ним относятся подделка межсайтовых запросов, фиксация сессии и атаки методом перебора.

Архитектура безопасности: концепция фильтров

Чтобы понять, как Spring Security перехватывает запросы, необходимо вспомнить базовое устройство сервлет-контейнеров (например, Tomcat). Любой HTTP-запрос, прежде чем попасть в контроллер с бизнес-логикой, проходит через цепочку сервлетных фильтров.

Spring Security встраивается в эту систему, но делает это элегантно, не смешивая конфигурацию веб-сервера и контекст приложения Spring.

| Компонент | Зона ответственности | Среда выполнения | | --- | --- | --- | | Стандартный Servlet Filter | Базовая обработка HTTP-запросов (кодировка, логирование) | Сервлет-контейнер (Tomcat, Jetty) | | DelegatingFilterProxy | Связующее звено между контейнером и Spring | Сервлет-контейнер | | FilterChainProxy | Управление маршрутизацией запросов по цепочкам безопасности | Spring ApplicationContext | | Security Filter | Конкретная логика безопасности (проверка токена, пароля) | Spring ApplicationContext |

Главным мостом между миром сервлетов и миром Spring выступает DelegatingFilterProxy. Это стандартный фильтр сервлетов, который сам по себе не выполняет логику безопасности. Его единственная задача — перехватить запрос и передать его специальному бину внутри контекста Spring, который называется FilterChainProxy.

Как устроен FilterChainProxy

FilterChainProxy — это сердце архитектуры Spring Security. Он содержит в себе одну или несколько цепочек фильтров, известных как SecurityFilterChain. Каждая такая цепочка привязана к определенному шаблону URL и содержит свой собственный набор правил и фильтров.

В примере выше создается цепочка, которая разрешает свободный доступ ко всем URL, начинающимся с /public/, а для всех остальных требует базовую аутентификацию.

Если приложение обрабатывает 1 000 запросов в секунду, и 200 из них идут на публичные эндпоинты, FilterChainProxy мгновенно определит, что для этих 200 запросов нужно применить одну цепочку (или вообще пропустить без строгих проверок), а оставшиеся 800 направить через полную цепочку аутентификации. Это обеспечивает высокую производительность маршрутизации.

Основные фильтры в стандартной цепочке

По умолчанию Spring Security 6.x настраивает цепочку, состоящую примерно из 12-16 фильтров. Порядок их выполнения строго регламентирован, так как каждый последующий фильтр может зависеть от результатов работы предыдущего.

Рассмотрим ключевые фильтры в порядке их вызова:

  • SecurityContextHolderFilter — восстанавливает контекст безопасности из сессии. Если пользователь уже логинился ранее, этот фильтр достанет его данные и поместит в текущий поток выполнения.
  • CsrfFilter — проверяет наличие и валидность CSRF-токена для запросов, изменяющих состояние (POST, PUT, DELETE). Защищает от выполнения несанкционированных действий от лица пользователя.
  • UsernamePasswordAuthenticationFilter — перехватывает запросы на URL авторизации (обычно /login), извлекает логин и пароль из формы и пытается аутентифицировать пользователя.
  • BasicAuthenticationFilter — проверяет наличие заголовка Authorization с закодированными учетными данными по стандарту HTTP Basic.
  • AuthorizationFilter — находится в самом конце цепочки. Он проверяет, имеет ли уже аутентифицированный пользователь права для доступа к запрошенному ресурсу.
  • Влияние фильтров на производительность

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

    Где — общее время обработки запроса, — сетевая задержка передачи данных, — количество фильтров в цепочке SecurityFilterChain, — время выполнения -го фильтра, а — время выполнения бизнес-логики в контроллере.

    Допустим, сетевая задержка составляет 40 мс, а выполнение бизнес-логики в контроллере занимает 150 мс. Если в цепочке настроено 15 фильтров, и каждый в среднем выполняется за 1 мс, то суммарное время работы Spring Security составит 15 мс. Общее время ответа будет равно 205 мс. В данном случае накладные расходы на безопасность составляют всего около 7% от общего времени, что является отличным показателем для enterprise-приложений.

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