Ответ
Spring Security связывает запрос с пользователем через объект Authentication, который хранится в SecurityContext, привязанном к текущему потоку выполнения (ThreadLocal).
Последовательность при обработке запроса:
SecurityContextPersistenceFilterвосстанавливаетSecurityContextдля текущего запроса (например, из HTTP-сессии) или создает новый.- Фильтр аутентификации (например,
UsernamePasswordAuthenticationFilterдля формы логина илиBearerTokenAuthenticationFilterдля JWT) проверяет запрос. - При успешной проверке создается заполненный объект
Authentication(с principal, authorities) и устанавливается вSecurityContext. - Контекст сохраняется в
SecurityContextHolder, делая пользователя доступным на протяжении всего запроса.
Пример получения данных текущего пользователя в коде:
// Стандартный способ получения аутентификации
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
String username = authentication.getName();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
// ... работа с данными пользователя
}
Ключевые моменты:
SecurityContextHolderпо умолчанию используетThreadLocal, поэтому контекст изолирован для каждого потока (запроса).- После обработки запроса
SecurityContextPersistenceFilterочищаетThreadLocal, чтобы избежать утечек памяти. - Для REST API (статус-лесс) контекст не сохраняется в сессии между запросами. Он воссоздается при каждом запросе на основе токена (JWT).