Ensure the AuthenticationManager is created when needed
There was too much state really in the old implementation of AuthenticationManagerConfiguration, and it was leading occasionally to null pointers when method A assumed that method B had already been called and it hadn't. This change manages to concentrate all the references to an AuthenticationManagerBuilder into a single method call, removoing the need for storing it at all. Fixes gh-1556
This commit is contained in:
parent
0950072b5e
commit
9902f98a3d
|
|
@ -26,6 +26,7 @@ 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;
|
||||
|
|
@ -41,9 +42,15 @@ import org.springframework.security.config.annotation.ObjectPostProcessor;
|
|||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Configuration for a Spring Security in-memory {@link AuthenticationManager}.
|
||||
* Configuration for a Spring Security in-memory {@link AuthenticationManager}. Can be
|
||||
* disabled by providing a bean of type AuthenticationManager. The value provided by this
|
||||
* configuration will become the "global" authentication manager (from Spring Security),
|
||||
* or the parent of the global instance. Thus it acts as a fallback when no others are
|
||||
* provided, is used by method security if enabled, and as a parent authentication manager
|
||||
* for "local" authentication managers in individual filter chains.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Rob Winch
|
||||
|
|
@ -53,8 +60,15 @@ import org.springframework.security.config.annotation.authentication.configurers
|
|||
@ConditionalOnMissingBean(AuthenticationManager.class)
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 3)
|
||||
public class AuthenticationManagerConfiguration extends
|
||||
GlobalAuthenticationConfigurerAdapter implements
|
||||
ApplicationListener<ContextRefreshedEvent> {
|
||||
GlobalAuthenticationConfigurerAdapter {
|
||||
|
||||
/*
|
||||
* Yes, this class is a GlobalAuthenticationConfigurerAdapter, even though none of
|
||||
* those methods are overridden: we want Spring Security to instantiate us early, so
|
||||
* we can in turn force the SecurityPrequisites to be instantiated. This will prevent
|
||||
* ordering issues between Spring Boot modules when they need to influence the default
|
||||
* security configuration.
|
||||
*/
|
||||
|
||||
private static Log logger = LogFactory
|
||||
.getLog(AuthenticationManagerConfiguration.class);
|
||||
|
|
@ -62,43 +76,48 @@ public class AuthenticationManagerConfiguration extends
|
|||
@Autowired
|
||||
private List<SecurityPrequisite> dependencies;
|
||||
|
||||
@Autowired
|
||||
private ObjectPostProcessor<Object> objectPostProcessor;
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties security;
|
||||
|
||||
@Autowired
|
||||
private AuthenticationEventPublisher authenticationEventPublisher;
|
||||
|
||||
private BootDefaultingAuthenticationConfigurerAdapter configurer = new BootDefaultingAuthenticationConfigurerAdapter();
|
||||
|
||||
@Override
|
||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.apply(this.configurer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
this.configurer.configureParent(auth);
|
||||
}
|
||||
private ObjectPostProcessor<Object> objectPostProcessor;
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public AuthenticationManager authenticationManager() {
|
||||
AuthenticationManager manager = this.configurer.getAuthenticationManagerBuilder()
|
||||
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
/*
|
||||
* This AuthenticationManagerBuilder is for the global AuthenticationManager
|
||||
*/
|
||||
BootDefaultingAuthenticationConfigurerAdapter configurer = new BootDefaultingAuthenticationConfigurerAdapter();
|
||||
configurer.init(auth);
|
||||
configurer.configure(auth);
|
||||
AuthenticationManager manager = configurer.getAuthenticationManagerBuilder()
|
||||
.getOrBuild();
|
||||
configurer.configureParent(auth);
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
AuthenticationManager manager = this.configurer.getAuthenticationManagerBuilder()
|
||||
.getOrBuild();
|
||||
if (manager instanceof ProviderManager) {
|
||||
((ProviderManager) manager)
|
||||
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
||||
@Component
|
||||
protected static class AuthenticationManagerConfigurationListener implements
|
||||
ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationEventPublisher authenticationEventPublisher;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
ApplicationContext context = event.getApplicationContext();
|
||||
if (context.getBeanNamesForType(AuthenticationManager.class).length == 0) {
|
||||
return;
|
||||
}
|
||||
AuthenticationManager manager = context.getBean(AuthenticationManager.class);
|
||||
if (manager instanceof ProviderManager) {
|
||||
((ProviderManager) manager)
|
||||
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -163,7 +182,8 @@ public class AuthenticationManagerConfiguration extends
|
|||
.roles(roles.toArray(new String[roles.size()])).and().and().build();
|
||||
|
||||
// Defer actually setting the parent on the AuthenticationManagerBuilder
|
||||
// because it makes it "configured" and we are only in the init() phase here.
|
||||
// because it makes it "configured" and we are only in the init() phase
|
||||
// here.
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ public class SampleWebSecureApplication extends WebMvcConfigurerAdapter {
|
|||
.password("admin").roles("ADMIN", "USER").and().withUser("user")
|
||||
.password("user").roles("USER");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue