Commit bdd61b8e authored by Phillip Webb's avatar Phillip Webb

Merge branch '1.1.x' into 1.2.x

parents 1f40c8a9 8b979fa2
...@@ -22,12 +22,14 @@ import java.util.Set; ...@@ -22,12 +22,14 @@ import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
...@@ -70,55 +72,33 @@ public class AuthenticationManagerConfiguration { ...@@ -70,55 +72,33 @@ public class AuthenticationManagerConfiguration {
@Bean @Bean
@Primary @Primary
public AuthenticationManager authenticationManager(AuthenticationConfiguration auth) public AuthenticationManager authenticationManager(
throws Exception { AuthenticationConfiguration configuration) throws Exception {
return auth.getAuthenticationManager(); return configuration.getAuthenticationManager();
} }
@Bean @Bean
public static BootDefaultingAuthenticationConfigurerAdapter bootDefaultingAuthenticationConfigurerAdapter( public static SpringBootAuthenticationConfigurerAdapter springBootAuthenticationConfigurerAdapter(
SecurityProperties security, List<SecurityPrerequisite> dependencies) { SecurityProperties securityProperties, List<SecurityPrerequisite> dependencies) {
return new BootDefaultingAuthenticationConfigurerAdapter(security); return new SpringBootAuthenticationConfigurerAdapter(securityProperties);
}
@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);
}
}
} }
/** /**
* We must add {@link BootDefaultingAuthenticationConfigurerAdapter} in the init phase * {@link GlobalAuthenticationConfigurerAdapter} to apply
* of the last {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the * {@link DefaultInMemoryUserDetailsManagerConfigurer}. We must apply
* typical flow is something like: * {@link DefaultInMemoryUserDetailsManagerConfigurer} in the init phase of the last
* {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the typical flow
* is something like:
*
* <ul> * <ul>
* <li>A * <li>A
* {@link GlobalAuthenticationConfigurerAdapter#init(AuthenticationManagerBuilder)} * {@link GlobalAuthenticationConfigurerAdapter#init(AuthenticationManagerBuilder)}
* exists that adds a {@link SecurityConfigurer} to the * exists that adds a {@link SecurityConfigurer} to the
* {@link AuthenticationManagerBuilder}</li> * {@link AuthenticationManagerBuilder}.</li>
* <li> * <li>
* {@link AuthenticationManagerConfiguration#init(AuthenticationManagerBuilder)} adds * {@link AuthenticationManagerConfiguration#init(AuthenticationManagerBuilder)} adds
* BootDefaultingAuthenticationConfigurerAdapter so it is after the * {@link SpringBootAuthenticationConfigurerAdapter} so it is after the
* {@link SecurityConfigurer} in the first step</li> * {@link SecurityConfigurer} in the first step.</li>
* <li>We then can default an {@link AuthenticationProvider} if necessary. Note we can * <li>We then can default an {@link AuthenticationProvider} if necessary. Note we can
* only invoke the * only invoke the
* {@link AuthenticationManagerBuilder#authenticationProvider(AuthenticationProvider)} * {@link AuthenticationManagerBuilder#authenticationProvider(AuthenticationProvider)}
...@@ -128,70 +108,106 @@ public class AuthenticationManagerConfiguration { ...@@ -128,70 +108,106 @@ public class AuthenticationManagerConfiguration {
* </ul> * </ul>
*/ */
@Order(Ordered.LOWEST_PRECEDENCE - 100) @Order(Ordered.LOWEST_PRECEDENCE - 100)
private static class BootDefaultingAuthenticationConfigurerAdapter extends private static class SpringBootAuthenticationConfigurerAdapter extends
GlobalAuthenticationConfigurerAdapter { GlobalAuthenticationConfigurerAdapter {
private final SecurityProperties security;
private final SecurityProperties securityProperties;
@Autowired @Autowired
public BootDefaultingAuthenticationConfigurerAdapter(SecurityProperties security) { public SpringBootAuthenticationConfigurerAdapter(
this.security = security; SecurityProperties securityProperties) {
this.securityProperties = securityProperties;
} }
@Override @Override
public void init(AuthenticationManagerBuilder auth) throws Exception { 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.
* /**
* <ul> * {@link InMemoryUserDetailsManagerConfigurer} to add user details from
* <li>A GlobalAuthenticationConfigurerAdapter will initialize the * {@link SecurityProperties}. This is necessary to delay adding the default user.
* AuthenticationManagerBuilder with a Configurer which will be after any *
* GlobalAuthenticationConfigurerAdapter</li> * <ul>
* <li>BootDefaultingAuthenticationConfigurerAdapter will be invoked after all * <li>A {@link GlobalAuthenticationConfigurerAdapter} will initialize the
* GlobalAuthenticationConfigurerAdapter, but before the Configurers that were * {@link AuthenticationManagerBuilder} with a Configurer which will be after any
* added by other GlobalAuthenticationConfigurerAdapter instances</li> * {@link GlobalAuthenticationConfigurerAdapter}.</li>
* <li>BootDefaultingAuthenticationConfigurerAdapter will add * <li>{@link SpringBootAuthenticationConfigurerAdapter} will be invoked after all
* DefaultingInMemoryUserDetailsManagerConfigurer after all Configurer instances</li> * {@link GlobalAuthenticationConfigurerAdapter}, but before the Configurers that were
* <li>All init methods will be invoked</li> * added by other {@link GlobalAuthenticationConfigurerAdapter} instances.</li>
* <li>All configure methods will be invoked which is where the * <li>A {@link SpringBootAuthenticationConfigurerAdapter} will add
* AuthenticationProvider instances are setup</li> * {@link DefaultInMemoryUserDetailsManagerConfigurer} after all Configurer instances.
* <li>If no AuthenticationProviders were provided, * </li>
* DefaultingInMemoryUserDetailsManagerConfigurer will default the value</li> * <li>All init methods will be invoked.</li>
* </ul> * <li>All configure methods will be invoked which is where the
* * {@link AuthenticationProvider} instances are setup.</li>
* @author Rob Winch * <li>If no AuthenticationProviders were provided,
*/ * {@link DefaultInMemoryUserDetailsManagerConfigurer} will default the value.</li>
private static class DefaultingInMemoryUserDetailsManagerConfigurer extends * </ul>
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> { */
private final SecurityProperties security; private static class DefaultInMemoryUserDetailsManagerConfigurer extends
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> {
public DefaultingInMemoryUserDetailsManagerConfigurer(
SecurityProperties security) { private final SecurityProperties securityProperties;
this.security = security;
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<String> roles = new LinkedHashSet<String>(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 { * {@link ApplicationListener} to autowire the {@link AuthenticationEventPublisher}
if (auth.isConfigured()) { * into the {@link AuthenticationManager}.
return; */
} @Component
protected static class AuthenticationManagerConfigurationListener implements
SmartInitializingSingleton {
User user = this.security.getUser(); @Autowired
if (user.isDefaultPassword()) { private AuthenticationEventPublisher eventPublisher;
logger.info("\n\nUsing default security password: "
+ user.getPassword() + "\n");
}
Set<String> roles = new LinkedHashSet<String>(user.getRole()); @Autowired
withUser(user.getName()).password(user.getPassword()).roles( private ApplicationContext context;
roles.toArray(new String[roles.size()]));
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 }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment