diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java index 74cd06b8a7b..45c2b846e8e 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java @@ -22,12 +22,14 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @@ -70,55 +72,33 @@ public class AuthenticationManagerConfiguration { @Bean @Primary - public AuthenticationManager authenticationManager(AuthenticationConfiguration auth) - throws Exception { - return auth.getAuthenticationManager(); + public AuthenticationManager authenticationManager( + AuthenticationConfiguration configuration) throws Exception { + return configuration.getAuthenticationManager(); } @Bean - public static BootDefaultingAuthenticationConfigurerAdapter bootDefaultingAuthenticationConfigurerAdapter( - SecurityProperties security, List dependencies) { - return new BootDefaultingAuthenticationConfigurerAdapter(security); - } - - @Component - protected static class AuthenticationManagerConfigurationListener implements - SmartInitializingSingleton { - - @Autowired - private AuthenticationEventPublisher authenticationEventPublisher; - - @Autowired - private ApplicationContext context; - - @Override - public void afterSingletonsInstantiated() { - if (this.context.getBeanNamesForType(AuthenticationManager.class).length == 0) { - return; - } - AuthenticationManager manager = this.context - .getBean(AuthenticationManager.class); - if (manager instanceof ProviderManager) { - ((ProviderManager) manager) - .setAuthenticationEventPublisher(this.authenticationEventPublisher); - } - } - + public static SpringBootAuthenticationConfigurerAdapter springBootAuthenticationConfigurerAdapter( + SecurityProperties securityProperties, List dependencies) { + return new SpringBootAuthenticationConfigurerAdapter(securityProperties); } /** - * We must add {@link BootDefaultingAuthenticationConfigurerAdapter} in the init phase - * of the last {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the - * typical flow is something like: + * {@link GlobalAuthenticationConfigurerAdapter} to apply + * {@link DefaultInMemoryUserDetailsManagerConfigurer}. We must apply + * {@link DefaultInMemoryUserDetailsManagerConfigurer} in the init phase of the last + * {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the typical flow + * is something like: + * * */ @Order(Ordered.LOWEST_PRECEDENCE - 100) - private static class BootDefaultingAuthenticationConfigurerAdapter extends + private static class SpringBootAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { - private final SecurityProperties security; + + private final SecurityProperties securityProperties; @Autowired - public BootDefaultingAuthenticationConfigurerAdapter(SecurityProperties security) { - this.security = security; + public SpringBootAuthenticationConfigurerAdapter( + SecurityProperties securityProperties) { + this.securityProperties = securityProperties; } @Override public void init(AuthenticationManagerBuilder auth) throws Exception { - auth.apply(new DefaultingInMemoryUserDetailsManagerConfigurer(this.security)); + auth.apply(new DefaultInMemoryUserDetailsManagerConfigurer( + this.securityProperties)); } - /** - * This is necessary to delay adding the default user. - * - * - * - * @author Rob Winch - */ - private static class DefaultingInMemoryUserDetailsManagerConfigurer extends - InMemoryUserDetailsManagerConfigurer { - private final SecurityProperties security; - - public DefaultingInMemoryUserDetailsManagerConfigurer( - SecurityProperties security) { - this.security = security; + } + + /** + * {@link InMemoryUserDetailsManagerConfigurer} to add user details from + * {@link SecurityProperties}. This is necessary to delay adding the default user. + * + *
    + *
  • A {@link GlobalAuthenticationConfigurerAdapter} will initialize the + * {@link AuthenticationManagerBuilder} with a Configurer which will be after any + * {@link GlobalAuthenticationConfigurerAdapter}.
  • + *
  • {@link SpringBootAuthenticationConfigurerAdapter} will be invoked after all + * {@link GlobalAuthenticationConfigurerAdapter}, but before the Configurers that were + * added by other {@link GlobalAuthenticationConfigurerAdapter} instances.
  • + *
  • A {@link SpringBootAuthenticationConfigurerAdapter} will add + * {@link DefaultInMemoryUserDetailsManagerConfigurer} after all Configurer instances. + *
  • + *
  • All init methods will be invoked.
  • + *
  • All configure methods will be invoked which is where the + * {@link AuthenticationProvider} instances are setup.
  • + *
  • If no AuthenticationProviders were provided, + * {@link DefaultInMemoryUserDetailsManagerConfigurer} will default the value.
  • + *
+ */ + private static class DefaultInMemoryUserDetailsManagerConfigurer extends + InMemoryUserDetailsManagerConfigurer { + + private final SecurityProperties securityProperties; + + public DefaultInMemoryUserDetailsManagerConfigurer( + SecurityProperties securityProperties) { + this.securityProperties = securityProperties; + } + + @Override + public void configure(AuthenticationManagerBuilder auth) throws Exception { + if (auth.isConfigured()) { + return; + } + User user = this.securityProperties.getUser(); + if (user.isDefaultPassword()) { + logger.info("\n\nUsing default security password: " + user.getPassword() + + "\n"); } + Set roles = new LinkedHashSet(user.getRole()); + withUser(user.getName()).password(user.getPassword()).roles( + roles.toArray(new String[roles.size()])); + super.configure(auth); + } + + } - @Override - public void configure(AuthenticationManagerBuilder auth) throws Exception { - if (auth.isConfigured()) { - return; - } + /** + * {@link ApplicationListener} to autowire the {@link AuthenticationEventPublisher} + * into the {@link AuthenticationManager}. + */ + @Component + protected static class AuthenticationManagerConfigurationListener implements + SmartInitializingSingleton { - User user = this.security.getUser(); - if (user.isDefaultPassword()) { - logger.info("\n\nUsing default security password: " - + user.getPassword() + "\n"); - } + @Autowired + private AuthenticationEventPublisher eventPublisher; - Set roles = new LinkedHashSet(user.getRole()); - withUser(user.getName()).password(user.getPassword()).roles( - roles.toArray(new String[roles.size()])); + @Autowired + private ApplicationContext context; - super.configure(auth); + @Override + public void afterSingletonsInstantiated() { + try { + configureAuthenticationManager(this.context + .getBean(AuthenticationManager.class)); } + catch (NoSuchBeanDefinitionException ex) { + // Ignore + } + } + private void configureAuthenticationManager(AuthenticationManager manager) { + if (manager instanceof ProviderManager) { + ((ProviderManager) manager) + .setAuthenticationEventPublisher(this.eventPublisher); + } } } -} \ No newline at end of file + +}