Меня очень смущают новые сопоставители Spring Security. Мой текущий код (SecurityConfiguration
расширяет WebSecurityConfigurerAdapter
):
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/some/endpoint")
.addFilterBefore(new CustomFilter(), BasicAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
Что будет эквивалентно SecurityConfiguration
? Я зашел так далеко, но, похоже, это работает не так, как ожидалось:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
return http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authz ->
authz.requestMatchers("/some/endpoint").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(new CustomFilter(), BasicAuthenticationFilter.class)
.sessionManagement(sessionManagementConfigurer -> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.build();
}
Теперь я вижу, что большинство моих вызовов на открытие URL-адресов типа /actuator/health
заблокированы.
Я также прочитал в руководстве по миграции:
В Spring Security 5.8 и более ранних версиях запросы без правила авторизации разрешены по умолчанию.
Каков наилучший подход?
Спасибо за ваше предложение. Это отличается. В качестве примера я привел здоровье, но у меня гораздо больше конечных точек. Фактически защищена только одна конечная точка, остальные открыты.
Тогда вам придется открыть и все остальные. Просто добавьте остальные. Ваш собственный ответ — плохая практика, вы не должны разрешать «любой запрос». Однако ваш старый код также является плохой практикой, не используйте antMatcher
, если у вас только одна цепочка фильтров.
Мне нужно было переключиться, чтобы это заработало:
authz.requestMatchers("/some/endpoint").permitAll()
.anyRequest().authenticated()
к
authz.requestMatchers("/some/endpoint").authenticated()
.anyRequest().permitAll()
Более чистый способ (предложенный @KenS) — создать два компонента безопасности:
@Order(0)
@Bean
public SecurityFilterChain secureEndpoint(HttpSecurity httpSecurity) throws Exception {
return httpSecurity.csrf(AbstractHttpConfigurer::disable)
.securityMatcher("/secure-endpoints/**")
.authorizeHttpRequests(authorize -> authorize
.anyRequest()
.authenticated()
)
.addFilterBefore(new CustomFilter(), BasicAuthenticationFilter.class)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.build();
}
@Order(1)
@Bean
public SecurityFilterChain openEndpoints(HttpSecurity http) throws Exception {
return http.csrf(AbstractHttpConfigurer::disable).securityMatcher("/open-endpoints/**")
.authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll()
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.build();
}
Хотя это не эквивалентно. Взгляните на SecurityMatcher как на замену antMatcher. См. примеры docs.spring.io/spring-security/reference/5.8/migration/servlet/…. Если у вас есть только один bean-компонент SecurityFilterChain, ваше решение также должно работать.
У меня есть только один bean-компонент SecurityFilterChain. Я вижу, что это работает. Я хотел бы узнать, как это будет работать правильно (например, исходная настройка). Понадобятся ли мне 2 bean-компонента: один для защищенных и один для открытых конечных точек?
Я бы сделал именно так, но ваше решение подходит для вашего примера. У вас может быть текущий SecurityFilterChain с http.securityMatchers("/some/endpoint").authorizeHttpRequests(authz -> authz.anyRequest().authenticated())
и второй без SecurityMatchers и authz.anyRequest().permitAll()
. Обязательно добавьте аннотации @Order(...) для обоих bean-компонентов, чтобы определить их порядок (меньшее число имеет приоритет). Для более сложных конфигураций см. docs.spring.io/spring-security/reference/servlet/configuration/… для начала.
Самое большое преимущество использования нескольких bean-компонентов SecurityFilterChain — это когда вам нужно иметь разные механизмы авторизации для разных точек входа. Вы можете защитить свою «/some/endpoint» с помощью CustomFilter, «/another/endpoint» с помощью oauth2, использовать базовую аутентификацию для привода и «denyAll» для всего остального.
@KenS Я обновил решение с учетом вашего предложения. Я попробовал, и это работает. Мне это нравится гораздо больше.
Отвечает ли это на ваш вопрос? Защита конечных точек исполнительного механизма, кроме /health