Как определялась последовательность фильтров в Spring Security: по заданию или самостоятельно
Что проверяют
Формально вопрос про ваш опыт, по сути про то, понимаете ли вы, что порядок встроенных фильтров задаёт сам фреймворк, а решать приходится только, куда встанет ваш. Следом просят показать, где в цепочке стоит ваш JWT-фильтр и почему.
Как отвечать
Начните с честного ответа про роль: порядок задавал шаблон проекта или архитектор, либо вы встраивали фильтр сами. Дальше покажите механику:
- цепочка:
DelegatingFilterProxyпередаёт запрос вFilterChainProxy, тот выбирает первый подходящийSecurityFilterChain. Несколько цепочек упорядочивают через@Orderи разделяютsecurityMatcher; - встроенный порядок: зашит во фреймворке:
SecurityContextHolderFilter,CorsFilter,CsrfFilter,LogoutFilter, фильтры аутентификации,ExceptionTranslationFilter, в концеAuthorizationFilter. Менять его не нужно; - свой фильтр: встраивают относительно существующего через
addFilterBefore,addFilterAfterилиaddFilterAt. JWT-фильтр на базеOncePerRequestFilterобычно ставят передUsernamePasswordAuthenticationFilter. Для стандартных JWT естьoauth2ResourceServer, он сам добавляетBearerTokenAuthenticationFilter; - фактический порядок: при старте список фильтров каждой цепочки попадает в лог, если включён DEBUG для
org.springframework.security, а@EnableWebSecurity(debug = true)печатает цепочку на каждый запрос.
Пример из опыта: «базовую цепочку задавал шаблон сервиса, я добавил проверку API-ключа для внутренних вызовов отдельной цепочкой с @Order(1) на /internal/**». Подставьте свой случай. Если фильтры вы только использовали, так и скажите и объясните, куда поставили бы свой.
Где спотыкаются
Рассказывают, что расставили все фильтры вручную, и ставят CSRF в конец. На деле CsrfFilter работает раньше аутентификации, а для stateless API с токенами его обычно отключают.
Объявляют свой фильтр как @Component и заодно добавляют в цепочку. Spring Boot регистрирует его ещё и в сервлет-контейнере, фильтр срабатывает дважды; лечится FilterRegistrationBean с setEnabled(false).
Путают приоритет цепочек: цепочка без securityMatcher ловит всё, и если её @Order выше, узкая до запросов не доходит.