I have configured my websecurityconfig with mutliple entry points for my application.
With this configuration, all my api request fail.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig {
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter implements RequestMatcher {
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(basicAuthenticationProvider)
.authenticationProvider(jwtAuthenticationProvider);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
String apiRegex = "/(" + apiPrefix + "/)?api";
http
.securityMatcher("/api/**", "/" + apiPrefix + "/api/**")
.addFilterBefore(new RequestFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests((requests) -> requests
.requestMatchers(HttpMethod.GET, apiRegex, apiRegex + "/v\\d+").permitAll()
.anyRequest().authenticated()
)
.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.httpBasic((httpBasic) -> httpBasic.realmName("Realm"))
.exceptionHandling((exceptions) -> exceptions.authenticationEntryPoint(new RestApiAuthenticationEntryPoint()))
.x509((x509) -> x509.userDetailsService(x509UserDetailsService))
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}
@Configuration
@Order(2)
public class AnotherWebSecurtyConfigurator {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests
.requestMatchers(HttpMethod.OPTIONS).denyAll()
.anyRequest().authenticated())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}
}
But when i remove my second entry point, the requests are working fine. I am not sure what is causing the problem.
The @Order
annotation has no effect on the class marked with @Configuration
. So when you create multiple configurations with SecurityFilterChain beans, the order in which they are applied is not explicitly defined and depends on the order in which Spring will process the configuration classes. Also, your SecurityFilterChain beans have the same name. In Spring Boot, creating beans with the same name is not allowed by default, because each bean name must be unique in the application context. If you try to create multiple beans with the same name, Spring will throw a BeanDefinitionOverrideException, indicating a bean name conflict. Apparently, you have allowed bean overriding with the spring.main.allow-bean-definition-overriding
parameter. Therefore, in your situation, Spring creates only one bean, the one whose configuration file it processed last.
You need to use a single configuration file to define your security filters in the order you want them to be applied.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain firstFilterChain(HttpSecurity http) throws Exception {
...
}
@Bean
public SecurityFilterChain secondFilterChain(HttpSecurity http) throws Exception {
...
}
@Bean
public SecurityFilterChain lastFilterChain(HttpSecurity http) throws Exception {
...
}
}