Как Spring Security определяет, кому предоставить доступ к защищенному ресурсу?

«Как Spring Security определяет, кому предоставить доступ к защищенному ресурсу?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Spring Security принимает решение о доступе на основе цепочки фильтров (Filter Chain) и голосования (voting). Процесс состоит из двух основных этапов:

  1. Аутентификация (Authentication): Устанавливает, кто пользователь.
  2. Авторизация (Authorization): Проверяет, имеет ли аутентифицированный пользователь необходимые права.

Ключевые компоненты:

  • AuthenticationManager: Проверяет учетные данные (логин/пароль, токен).
  • AccessDecisionManager: Принимает итоговое решение о доступе, опрашивая список AccessDecisionVoter.
  • SecurityContextHolder: Хранит контекст безопасности (объект Authentication) для текущего потока.

Пример конфигурации авторизации:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated() // Требует аутентификации для всех остальных запросов
            );
        return http.build();
    }
}

Почему именно так? Механизм голосования (RoleVoter, AuthenticatedVoter) делает систему гибкой. Правила оцениваются в порядке их объявления — от наиболее специфичных к общим (anyRequest()).