Получить доступ

Метод помечен @Async, и внутри него SecurityContextHolder.getContext().getAuthentication() возвращает null. Почему?

MiddleSpring Security
Ещё спрашивают так:
  • Как передать пользователя в @Async-метод?
Коротко

SecurityContext хранится в ThreadLocal потока запроса и в асинхронный поток сам не переезжает. Решение — DelegatingSecurityContextAsyncTaskExecutor (или TaskDecorator), который копирует контекст.

  • То же для MDC с trace id — TaskDecorator
  • Режим MODE_INHERITABLETHREADLOCAL не подходит для пулов — потоки переиспользуются
  • Виртуальные потоки не меняют проблему

А ещё Context Propagation (Micrometer) переносит контекст автоматически

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Стратегия хранения по умолчанию — MODE_THREADLOCAL, поэтому любой переход в другой поток теряет контекст: это касается @Async, задач в собственном пуле и реактивных цепочек. Варианты решения: включить MODE_INHERITABLETHREADLOCAL, что работает для потоков, созданных напрямую, но бесполезно для пула, где потоки существовали заранее; либо, что правильнее, обернуть исполнитель в DelegatingSecurityContextExecutor или DelegatingSecurityContextAsyncTaskExecutor, который явно переносит контекст в задачу. В WebFlux механизм другой — контекст живёт в Reactor Context, а не в ThreadLocal. И совсем простой вариант: передать нужные данные о пользователе параметрами метода, не полагаясь на неявное состояние.

Что хотят услышать

  • Причина: ThreadLocal.
  • Правильное решение с executor'ом.
  • Почему не inheritable для пулов.

Частые ошибки

  • Рассчитывать, что MODE_INHERITABLETHREADLOCAL решит проблему для пула потоков.
  • Полагаться на SecurityContextHolder внутри реактивных цепочек.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓По умолчанию контекст хранится в ThreadLocal и не наследуется новым потоком — нужна стратегия наследования или делегирующий executor
  • ✗@Async несовместим со Spring Security
  • ✗Аутентификация истекает при выходе из метода контроллера
  • ✗Нужно пометить метод дополнительно аннотацией @PreAuthorize

Что спросят дальше

  • Почему наследуемый ThreadLocal не помогает с пулом?
  • Как устроено распространение контекста в WebFlux?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем