Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
271 views
in Technique[技术] by (71.8m points)

java - Using multiple WebSecurityConfigurerAdapter with different AuthenticationProviders (basic auth for API and LDAP for web app)

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 AuthenticationManagerBuilder is more widely applicable (see below for more detail on how web application security is implemented). Note that the AuthenticationManagerBuilder is @Autowired into 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 @Override of a method in the configurer) then the AuthenticationManagerBuilder is only used to build a "local" AuthenticationManager, which is a child of the global one.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...