Глобальный обработчик ошибок в Spring Boot, и причем тут безопасность?
Салимжанов Р.
Введение
Когда вы разрабатываете веб-приложение, ошибки неизбежны. Пользователь может ввести неверные данные, сервер временно недоступен, или в коде возникнет непредвиденная ситуация. Если приложение не обрабатывает ошибки правильно, это может привести к:
- Утечке конфиденциальной информации (например, паролей, SQL-запросов, структуры базы данных).
- Неудобству для пользователей (непонятные сообщения об ошибках или технические детали).
- Уязвимостям безопасности (злоумышленники могут использовать ошибки для атак).
Глобальный обработчик ошибок (Global Exception Handler) — это механизм Java в Spring Boot, который позволяет централизованно перехватывать и обрабатывать все исключения в приложении. В этой статье мы разберём:
- Зачем нужен глобальный обработчик ошибок?
- Как он связан с безопасностью?
- Пошаговая настройка в Spring Boot (с кодом).
1. Зачем нужен глобальный обработчик ошибок?
1.1. Единый формат ответов
Без обработчика разные ошибки могут возвращать ответы в разном формате:
❌ Плохо:
✅ Хорошо (с обработчиком):
1.2. Защита от утечки информации
По умолчанию Spring Boot может показывать стектрейс (stack trace) ошибки, что опасно:
🚨 Пример уязвимости:
Злоумышленник видит:
- Используется PostgreSQL.
- Есть SQL-инъекция (ошибка в запросе).
- Название таблицы или поля (admin).
✅ С обработчиком: Мы скрываем технические детали и возвращаем только безопасное сообщение.
1.3. Логирование ошибок
Глобальный обработчик позволяет централизованно логировать ошибки, что полезно для:
- Отладки.
- Обнаружения атак (например, если кто-то пытается вызвать ошибки специально).
2. Как это связано с безопасностью?
2.1. Предотвращение атак через ошибки
- SQL-инъекции — если в ошибке показывается SQL-запрос, злоумышленник может использовать это для взлома.
- Brute-force — если при логине возвращается разный текст ошибки для "неверный логин" и "неверный пароль", это помогает подбирать учётные данные.
- Информационная утечка — версии библиотек, структура БД, пути файлов.
2.2. OWASP рекомендации
По стандартам OWASP Топ 10:
URL:
- A01:2021 — Broken Access Control (неправильная обработка доступа).
- A03:2021 — Injection (ошибки, связанные с SQL, NoSQL, командами ОС).
- A05:2021 — Security Misconfiguration (неправильные настройки ошибок).
✅ Решение: Глобальный обработчик скрывает опасные детали.
3. Настройка глобального обработчика ошибок в Spring Boot
В этом разделе мы разберём, как именно работает глобальный обработчик исключений в Spring Boot, как его правильно настроить и какие компоненты за что отвечают.
3.1. Основные компоненты обработчика
@RestControllerAdvice — главная аннотация
Эта аннотация объединяет три функции:
- @ControllerAdvice — указывает, что класс обрабатывает исключения во всех контроллерах.
- @ResponseBody — автоматически преобразует возвращаемые объекты в JSON (как у @RestController).
- Централизованная обработка — все исключения из любых контроллеров будут проходить через этот класс.
3.2. Методы-обработчики (@ExceptionHandler)
Каждый метод, помеченный @ExceptionHandler, отвечает за конкретный тип ошибки. Spring вызывает соответствующий метод в зависимости от возникшего исключения.
Пример 1: Обработка кастомных исключений
Как это работает:
- Если в любом контроллере выброшено UserNotFoundException, Spring вызывает этот метод.
- Метод логирует событие (уровень WARN, так как это ожидаемая ошибка).
- Создаётся объект ErrorResponse с удобочитаемым сообщением.
- Клиент получает JSON с HTTP-статусом 404 (Not Found).
Пример 2: Обработка ошибок валидации (@Valid)
Когда данные не проходят валидацию (например, поле email пустое), Spring выбрасывает MethodArgumentNotValidException.
Как это работает:
- Spring автоматически проверяет входные данные при использовании @Valid.
- Если валидация не пройдена, вызывается этот метод.
- ex.getBindingResult().getFieldErrors() содержит список всех ошибок.
- Клиент получает 400 (Bad Request) с перечислением проблем.
Пример 3: Перехват всех необработанных исключений
Этот метод — "ловушка" для всех ошибок, которые не были перехвачены другими обработчиками.
Важные нюансы:
- Не показывайте ex.getMessage() в продакшене — это может раскрыть внутреннюю логику приложения.
- Логируйте полный стек только в режиме разработки (dev).
3.3. DTO для ошибок (ErrorResponse)
Этот класс определяет структуру JSON-ответа при ошибках.
3.4. Настройка application.properties
Добавьте эти строки, чтобы отключить опасные настройки Spring Boot по умолчанию:
3.5. Полный тестовый пример
HelloController:
GlobalExceptionHandler:
UserNotFoundException:
3.6. Как проверить обработчик?
Вывод
✅ Глобальный обработчик ошибок в Spring Boot:
- Даёт единый формат ответов.
- Защищает от утечки данных (SQL-ошибки, стектрейсы).
- Улучшает безопасность (скрывает детали реализации).
- Позволяет логировать ошибки для анализа атак.
Рекомендации:
- Не показывайте ex.getMessage() в продакшене — только общие сообщения.
- Логируйте ошибки, но без sensitive-данных.
- Ограничивайте частые ошибки (Rate Limiting).