Set UserDetailsService in default AuthenticationManagerBuilder

Only affects the default AuthenticationManagerBuilder (so when users
are not overriding the default global user details). Makes the
UserDetailsService effectively available as it would be if we used
AuthenticationManagerBuilder.inMemoryAuthentication() as a
shared object in the HttpSecurity.

Fixes gh-3152
This commit is contained in:
Dave Syer 2015-06-08 13:14:12 +01:00
parent c7103bf2a4
commit 1c0bcc13cf
2 changed files with 45 additions and 0 deletions

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.security;
import java.lang.reflect.Field;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@ -46,6 +47,7 @@ import org.springframework.security.config.annotation.authentication.configurati
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
/**
* Configuration for a Spring Security in-memory {@link AuthenticationManager}. Can be
@ -171,9 +173,21 @@ public class AuthenticationManagerConfiguration {
Set<String> roles = new LinkedHashSet<String>(user.getRole());
withUser(user.getName()).password(user.getPassword()).roles(
roles.toArray(new String[roles.size()]));
setField(auth, "defaultUserDetailsService", getUserDetailsService());
super.configure(auth);
}
private void setField(Object target, String name, Object value) {
try {
Field field = ReflectionUtils.findField(target.getClass(), name);
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, target, value);
}
catch (Exception e) {
logger.info("Could not set " + name);
}
}
}
/**

View File

@ -49,6 +49,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@ -190,6 +191,19 @@ public class SecurityAutoConfigurationTests {
this.context.getBean(AuthenticationManager.class));
}
@Test
public void testDefaultAuthenticationManagerMakesUserDetailsAvailable()
throws Exception {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(UserDetailsSecurityCustomizer.class,
SecurityAutoConfiguration.class, ServerPropertiesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(UserDetailsSecurityCustomizer.class)
.getUserDetails().loadUserByUsername("user"));
}
@Test
public void testOverrideAuthenticationManagerAndInjectIntoSecurityFilter()
throws Exception {
@ -380,4 +394,21 @@ public class SecurityAutoConfigurationTests {
}
@Configuration
protected static class UserDetailsSecurityCustomizer extends
WebSecurityConfigurerAdapter {
private UserDetailsService userDetails;
@Override
protected void configure(HttpSecurity http) throws Exception {
this.userDetails = http.getSharedObject(UserDetailsService.class);
}
public UserDetailsService getUserDetails() {
return this.userDetails;
}
}
}