Spring Security 6: SecurityFilterChain и цепочка фильтров
Безопасность в Spring — это цепочка фильтров, через которую проходит каждый запрос до контроллера. В Spring Security 6 она настраивается бином SecurityFilterChain.
Суть: запрос проходит фильтры безопасности до контроллера. В Security 6 конфигурация — это @Bean SecurityFilterChain с лямбда-DSL; WebSecurityConfigurerAdapter удалён, antMatchers заменён на requestMatchers.
Spring Security защищает приложение, вставляя перед контроллерами цепочку фильтров. Каждый фильтр решает свою задачу: проверить аутентификацию, авторизацию, CSRF и так далее. Запрос либо проходит всю цепочку и доходит до контроллера, либо отсекается с 401/403.
Современная конфигурация (Security 6)
Важно: старый стиль с наследованием от WebSecurityConfigurerAdapter удалён. Теперь вы объявляете бин SecurityFilterChain:
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(org.springframework.security.config.Customizer.withDefaults());
return http.build();
}
}
Это лямбда-DSL: каждая настройка — лямбда. requestMatchers (вместо устаревшего antMatchers) задаёт правила по путям: что открыто всем, что — только админам, что требует аутентификации.
Как работает под капотом
Запрос входит в FilterChainProxy и проходит фильтры по очереди. Один извлекает учётные данные, другой проверяет права на путь. Если правило не выполнено — цепочка прерывается с 401 (не аутентифицирован) или 403 (нет прав), и контроллер не вызывается.
Запрос GET /api/admin/users
|
v
Цепочка фильтров безопасности
┌──────────────────────────────────┐
│ 1. аутентификация (кто ты?) │
│ 2. авторизация (что тебе можно?) │
│ путь /api/admin -> нужен ADMIN │
└──────────────────────────────────┘
| |
правила ok? нет прав?
| |
v v
Controller 403 Forbidden
Смоделируем цепочку фильтров и проверку правил:
# Цепочка фильтров безопасности: правила по путям
rules = [
("/api/public", "permitAll"),
("/api/admin", "ROLE_ADMIN"),
("/api", "authenticated"),
]
def authorize(path, user):
for prefix, rule in rules:
if path.startswith(prefix):
if rule == "permitAll":
return 200
if user is None:
return 401 # не аутентифицирован
if rule == "authenticated":
return 200
if rule.startswith("ROLE_") and rule[5:] not in user["roles"]:
return 403 # нет прав
return 200
return 200
admin = {"name": "root", "roles": ["ADMIN"]}
guest = {"name": "guest", "roles": ["USER"]}
print(authorize("/api/public/info", None)) # 200
print(authorize("/api/admin/users", guest)) # 403
print(authorize("/api/admin/users", admin)) # 200
print(authorize("/api/orders", None)) # 401
Нажмите «Попробуй сам ▶»: правила по путям дают 200/401/403 — ровно как делает цепочка фильтров Spring Security.
Частые ошибки
- Искать WebSecurityConfigurerAdapter. Он удалён в Security 6 — используйте бин
SecurityFilterChain. - antMatchers вместо requestMatchers. Старый метод переименован; туториалы с
antMatchersустарели. - permitAll слишком широко. Лишний открытый путь — дыра в безопасности. Открывайте только нужное.
Best practices
- Конфигурируйте через бин
SecurityFilterChainи лямбда-DSL. - Закрывайте всё по умолчанию (
anyRequest().authenticated()), открывайте точечно. - Для разных групп путей можно завести несколько бинов
SecurityFilterChain.
Итог: Spring Security 6 — это цепочка фильтров, настраиваемая бином SecurityFilterChain с лямбда-DSL. Забудьте про WebSecurityConfigurerAdapter и antMatchers — это прошлое.