According the Spring Security Reference section 5.7 it should be possible to define more than one security adapter.
I try to do the same but without success. After a server reboot, the first x times the API works fine with basic auth, but after a couple of times I'm redirected to the login (form) page, this should only happen for our web app, not for the API calls.
My code:
@EnableWebSecurity
public class MultiHttpSecurityConfig  {
    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        @Autowired
        private Environment env;
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication().
                withUser("admin").password("pw_test").roles(API_ROLE);
        }
        protected void configure(HttpSecurity http) throws Exception {
            http
              .antMatcher("/services/**")
              .authorizeRequests()
              .anyRequest().hasRole(API_ROLE)
              .and()
              .httpBasic()
              .and()
              .csrf()
              .disable();
        }
    }
    @Configuration
    @Order(2)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        @Autowired
        private Environment env;
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
            auth.eraseCredentials(false);
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // LDAP FORM AUTHENTICATION
            http.authorizeRequests()
                .antMatchers("/login.html").permitAll()
                .antMatchers("/css/**").permitAll() 
                .antMatchers("/js/**").permitAll() 
                .antMatchers("/images/**").permitAll() 
                .anyRequest().authenticated()
            .and().formLogin()
                .failureUrl("/login.html?error=1")
                .loginPage("/login.html")
                .loginProcessingUrl("/j_spring_security_check")
                .defaultSuccessUrl("/success.html")
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .permitAll();
            http.csrf().disable();
            // iFRAMES SETTINGS
            http
                .headers()
                .frameOptions().sameOrigin()
                .httpStrictTransportSecurity().disable();
            // HTTPS
            http
                .requiresChannel()
                .anyRequest()
                .requiresSecure();
            //MAP 8080 to HTTPS PORT
            http.portMapper().http(8080).mapsTo(443);
        }
        @Bean
        public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
            CustomLdapAuthenticationProvider provider = new CustomLdapAuthenticationProvider(env.getProperty("ldap.domain"), env.getProperty("ldap.url"), env.getProperty("ldap.base"));
            provider.setConvertSubErrorCodesToExceptions(true);
            provider.setUseAuthenticationRequestCredentials(true);
            return provider;
        }
    }
}
Any idea?
I'm using Spring Boot version 1.4.1-RELEASE and Spring Security version 4.1.3-RELEASE.
You need to declare SecurityFilterChain and WebSecurityCustomizer beans instead of overriding methods of WebSecurityConfigurerAdapter class.
Step 1: Add the security jar or dependency in your application. Step 2: Create a security config class and extend the WebSecurityConfigurerAdapter class. Step 3: Add the annotation @EnableWebSecurity on top of the class. Step 4: For authentication, override the method configure(AuthenticationManagerBuilder auth) .
You use the same AuthenticationManager for both configurations, because you autowire the same AuthenticationManagerBuilder. 
See Spring Security Architecture:
@Configuration public class ApplicationSecurity extends WebSecurityConfigurerAdapter { ... // web stuff here @Autowired public void initialize(AuthenticationManagerBuilder builder, DataSource dataSource) { builder.jdbcAuthentication().dataSource(dataSource).withUser("dave") .password("secret").roles("USER"); } }This example relates to a web application, but the usage of
AuthenticationManagerBuilderis more widely applicable (see below for more detail on how web application security is implemented). Note that theAuthenticationManagerBuilderis@Autowiredinto a method in a@Bean- that is what makes it build the global (parent) AuthenticationManager. In contrast if we had done it this way:@Configuration public class ApplicationSecurity extends WebSecurityConfigurerAdapter { @Autowired DataSource dataSource; ... // web stuff here @Override public void configure(AuthenticationManagerBuilder builder) { builder.jdbcAuthentication().dataSource(dataSource).withUser("dave") .password("secret").roles("USER"); } }(using an
@Overrideof a method in the configurer) then theAuthenticationManagerBuilderis only used to build a "local"AuthenticationManager, which is a child of the global one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With