Использование нескольких WebSecurityConfigurerAdapter в spring для загрузки
У меня есть 2 класса, которые расширяют WebSecurityConfigurerAdapter
. И не могут заставить их работать вместе.
Идея такова:
- Есть один
WebSecurityConfigurerAdapter
, который добавляет специальный фильтр в цепочку безопасности. Фильтр выполняет некоторую пользовательскую аутентификацию и сохраняет Authentication
в SecurityContext
. Это нормально работает. Конфигурируется следующим образом (импорт пропущен):
@Order(1)
@Configuration
@EnableWebMvcSecurity
public class BestSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private BestPreAuthenticationFilter ssoAuthenticationFilter;
@Bean
protected FilterRegistrationBean getSSOAuthenticationFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(ssoAuthenticationFilter);
// Avoid include to the default chain
filterRegistrationBean.setEnabled(false);
return filterRegistrationBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(ssoAuthenticationFilter, SecurityContextPersistenceFilter.class);
}
@Configuration
protected static class AuthenticationConfiguration extends
GlobalAuthenticationConfigurerAdapter {
@Autowired
private BestAuthenticationProvider authenticationProvider;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
}
- Я хочу, чтобы вышеуказанное было своего рода классом библиотеки, который любой может включать через
@ComponentScan
, и получить упорядоченную проверку подлинности. Очевидно, что они хотят предоставить пользовательский HttpSecurity
для защиты информационных точек. Попробуйте что-то вроде:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/testUrl").hasRole("NON_EXISTING")
.anyRequest().authenticated();
}
}
Очевидно, что тестовый URL-адрес не должен быть доступен, так как мой пользователь не является членом роли NON_EXISTING
. К несчастью, она.
Если я переведу часть безопасности authorizeRequests()
в форму класса конфигурации 1. рядом с добавлением фильтра безопасности, он блокирует доступ, как ожидалось. Но в моем случае это выглядит как вторая конфигурация игнорируется.
Я также отлаживал методы configure()
и заметил, что HttpSecurity
- это не тот же объект, который немного пахнет.
Любые советы, как я могу сделать эту работу высоко оцененной.
Подведите итог цели:
- имеет один
WebSecurityConfigurerAdapter
, который добавляет фильтр и скрыт от пользователя библиотеки
- позволяет пользователю определить собственную пользовательскую безопасность конечных точек.
Spring boot 1.1.6-RELEASE
Ответы
Ответ 1
Определите специальный интерфейс
public interface ServiceWebSecurityConfigurer {
void configure(HttpSecurity http) throws Exception;
}
Затем выберите только один ConfigurerAdapter:
public class MyConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired(required = false)
ServiceWebSecurityConfigurer serviceSecConfig;
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests(). // whatever
if (serviceSecConfig != null) serviceSecConfig.configure(http);
http.authorizeRequests(). // whatever
}
}
а затем просто реализуйте ServiceWebSecurityConfigurer в другом месте, когда это необходимо. Также может быть несколько реализаций, просто соедините их автоматически в виде списка и итерируйте и используйте их все в вашей основной конфигурации.
Ответ 2
Итак, один из вариантов, который я только что нашел, это:
- Удалите аннотацию
@Configuration
с первого bean
И измените 2. на:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends BestSecurityConfig { //Note the changed extend !
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http); // Merge of the 2 HTTP configurations
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/testUrl").hasRole("NON_EXISTING")
.anyRequest().authenticated();
}
}
Любые комментарии относительно того, правильно ли это или неправильно подход
Изменить: Через несколько лет я все еще не нашел другого пути, но мне все больше нравится этот путь. Даже в случае по умолчанию вы расширяете абстрактный WebSecurityConfigurerAdapter
, нет причин, по которым какой-либо другой уровень абстракции не может предоставить другое абстрактное расширение, которое обеспечивает значимые значения по умолчанию.
Ответ 3
Я основал (на мой взгляд) более чистый способ структурирования некоторых конфигураций по умолчанию и упростил интеграцию в новые проекты с помощью пользовательских DSL.
Я использую его для настройки фильтров проверки подлинности JWT, но я думаю, что фильтр CORS более прост и дидактичен:
public class CustomCorsFilterDsl extends AbstractHttpConfigurer<CustomCorsFilterDsl, HttpSecurity> {
@Override
public void init(HttpSecurity http) throws Exception {
//your init code here, no needed in this case
}
@Override
public void configure(HttpSecurity http) throws Exception {
CorsFilter corsFilter = corsFilter(corsProperties);
http.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class);
}
private CorsFilter corsFilter(CorsProperties corsProperties) {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:9000");
config.addAllowedHeader("*");
config.addAllowedMethod("GET, POST, PUT, PATCH, DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
public static CustomCorsFilterDsl dsl() {
return new CustomCorsFilterDsl();
}
}
И в вашем WebSecurityConfig вы можете использовать его следующим образом:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/foo/**").permitAll()
//... your configurations
.antMatchers("/**").authenticated()
.and()
.apply(CustomCorsFilterDsl.dsl());
}
}
И вы достигли своей цели - иметь библиотеки с конфигурациями по умолчанию, не зависящие от кода ваших проектов, более понятным образом, поскольку вы можете визуализировать в проекте WebSecurityConfig собственную запись CORS.