Skip to content

Commit e42fa79

Browse files
Rob Winchdsyer
Rob Winch
authored andcommitted
Fix fragile AuthenticationManagerConfiguration
Fixes gh-2474
1 parent b8babd4 commit e42fa79

File tree

1 file changed

+25
-100
lines changed

1 file changed

+25
-100
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
3131
import org.springframework.context.annotation.Bean;
3232
import org.springframework.context.annotation.Configuration;
3333
import org.springframework.context.annotation.Primary;
34+
import org.springframework.core.Ordered;
3435
import org.springframework.core.annotation.Order;
3536
import org.springframework.security.authentication.AuthenticationEventPublisher;
3637
import org.springframework.security.authentication.AuthenticationManager;
@@ -39,9 +40,8 @@
3940
import org.springframework.security.config.annotation.ObjectPostProcessor;
4041
import org.springframework.security.config.annotation.SecurityConfigurer;
4142
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
43+
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
4244
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
43-
import org.springframework.security.core.Authentication;
44-
import org.springframework.security.core.AuthenticationException;
4545
import org.springframework.stereotype.Component;
4646

4747
/**
@@ -59,52 +59,24 @@
5959
@ConditionalOnBean(ObjectPostProcessor.class)
6060
@ConditionalOnMissingBean({ AuthenticationManager.class })
6161
@Order(0)
62-
public class AuthenticationManagerConfiguration extends
63-
GlobalAuthenticationConfigurerAdapter {
64-
65-
/*
66-
* Yes, this class is a GlobalAuthenticationConfigurerAdapter, even though none of
67-
* those methods are overridden: we want Spring Security to instantiate us early, so
68-
* we can in turn force the SecurityPrequisites to be instantiated. This will prevent
69-
* ordering issues between Spring Boot modules when they need to influence the default
70-
* security configuration.
71-
*/
62+
public class AuthenticationManagerConfiguration {
7263

7364
private static Log logger = LogFactory
7465
.getLog(AuthenticationManagerConfiguration.class);
7566

7667
@Autowired
7768
private List<SecurityPrerequisite> dependencies;
7869

79-
@Autowired
80-
private SecurityProperties security;
81-
82-
@Autowired
83-
private ObjectPostProcessor<Object> objectPostProcessor;
84-
8570
@Bean
8671
@Primary
87-
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth,
88-
ApplicationContext context) throws Exception {
89-
90-
if (isAuthenticationManagerAlreadyConfigured(context)) {
91-
return new LazyAuthenticationManager(auth);
92-
}
93-
94-
/*
95-
* This AuthenticationManagerBuilder is for the global AuthenticationManager
96-
*/
97-
BootDefaultingAuthenticationConfigurerAdapter configurer = new BootDefaultingAuthenticationConfigurerAdapter();
98-
configurer.configure(auth);
99-
AuthenticationManager manager = configurer.getAuthenticationManagerBuilder()
100-
.getOrBuild();
101-
configurer.configureParent(auth);
102-
return manager;
103-
72+
public AuthenticationManager authenticationManager(AuthenticationConfiguration auth) throws Exception {
73+
return auth.getAuthenticationManager();
10474
}
10575

106-
private boolean isAuthenticationManagerAlreadyConfigured(ApplicationContext context) {
107-
return context.getBeanNamesForType(GlobalAuthenticationConfigurerAdapter.class).length > 2;
76+
@Bean
77+
public static BootDefaultingAuthenticationConfigurerAdapter bootDefaultingAuthenticationConfigurerAdapter(SecurityProperties security,
78+
List<SecurityPrerequisite> dependencies) {
79+
return new BootDefaultingAuthenticationConfigurerAdapter(security);
10880
}
10981

11082
@Component
@@ -128,10 +100,6 @@ public void afterSingletonsInstantiated() {
128100
((ProviderManager) manager)
129101
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
130102
}
131-
else if (manager instanceof LazyAuthenticationManager) {
132-
((LazyAuthenticationManager) manager)
133-
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
134-
}
135103
}
136104

137105
}
@@ -157,74 +125,31 @@ else if (manager instanceof LazyAuthenticationManager) {
157125
* methods are invoked before configure, which cannot be guaranteed at this point.</li>
158126
* </ul>
159127
*/
160-
private class BootDefaultingAuthenticationConfigurerAdapter {
161-
162-
private AuthenticationManagerBuilder defaultAuth;
163-
164-
private AuthenticationManager parent;
128+
@Order(Ordered.LOWEST_PRECEDENCE - 100)
129+
private static class BootDefaultingAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
130+
private final SecurityProperties security;
165131

166-
public void configureParent(AuthenticationManagerBuilder auth) {
167-
if (!auth.isConfigured() && this.parent != null) {
168-
auth.parentAuthenticationManager(this.parent);
169-
}
170-
}
171-
172-
public AuthenticationManagerBuilder getAuthenticationManagerBuilder() {
173-
return this.defaultAuth;
132+
@Autowired
133+
public BootDefaultingAuthenticationConfigurerAdapter(SecurityProperties security) {
134+
this.security = security;
174135
}
175136

176-
public void configure(AuthenticationManagerBuilder auth) throws Exception {
137+
public void init(AuthenticationManagerBuilder auth) throws Exception {
177138
if (auth.isConfigured()) {
178-
this.defaultAuth = auth;
179139
return;
180140
}
181-
User user = AuthenticationManagerConfiguration.this.security.getUser();
141+
142+
User user = this.security.getUser();
182143
if (user.isDefaultPassword()) {
183144
logger.info("\n\nUsing default security password: " + user.getPassword()
184145
+ "\n");
185146
}
186-
this.defaultAuth = new AuthenticationManagerBuilder(
187-
AuthenticationManagerConfiguration.this.objectPostProcessor);
188147
Set<String> roles = new LinkedHashSet<String>(user.getRole());
189-
this.parent = this.defaultAuth.inMemoryAuthentication()
190-
.withUser(user.getName()).password(user.getPassword())
191-
.roles(roles.toArray(new String[roles.size()])).and().and().build();
192-
// Defer actually setting the parent on the AuthenticationManagerBuilder
193-
// because it makes it "configured" and we are only in the init() phase
194-
// here.
148+
auth
149+
.inMemoryAuthentication()
150+
.withUser(user.getName())
151+
.password(user.getPassword())
152+
.roles(roles.toArray(new String[roles.size()]));
195153
}
196154
}
197-
198-
private static class LazyAuthenticationManager implements AuthenticationManager {
199-
200-
private AuthenticationManagerBuilder builder;
201-
202-
private AuthenticationManager authenticationManager;
203-
204-
private AuthenticationEventPublisher authenticationEventPublisher;
205-
206-
public LazyAuthenticationManager(AuthenticationManagerBuilder builder) {
207-
this.builder = builder;
208-
}
209-
210-
public void setAuthenticationEventPublisher(
211-
AuthenticationEventPublisher authenticationEventPublisher) {
212-
this.authenticationEventPublisher = authenticationEventPublisher;
213-
}
214-
215-
@Override
216-
public Authentication authenticate(Authentication authentication)
217-
throws AuthenticationException {
218-
if (this.authenticationManager == null) {
219-
this.authenticationManager = this.builder.getOrBuild();
220-
if (this.authenticationManager instanceof ProviderManager) {
221-
((ProviderManager) this.authenticationManager)
222-
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
223-
}
224-
}
225-
return this.authenticationManager.authenticate(authentication);
226-
}
227-
228-
}
229-
230-
}
155+
}

0 commit comments

Comments
 (0)