Refactoring of UserDetailsService injection (for X509, OpenID and RememberMeServices) to use a factory bean rather than a post-processor.
This commit is contained in:
parent
74896f217b
commit
d3d9c5db59
|
@ -19,6 +19,7 @@ public abstract class BeanIds {
|
|||
public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX + "contextSettingPostProcessor";
|
||||
|
||||
public static final String USER_DETAILS_SERVICE = PREFIX + "userDetailsService";
|
||||
public static final String USER_DETAILS_SERVICE_FACTORY = PREFIX + "userDetailsServiceFactory";
|
||||
|
||||
public static final String METHOD_ACCESS_MANAGER = PREFIX + "defaultMethodAccessManager";
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
|
|||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationProvider;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.config.Elements;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
||||
|
@ -119,7 +119,7 @@ final class AuthenticationConfigBuilder {
|
|||
createX509Filter(authenticationManager);
|
||||
createLogoutFilter();
|
||||
createLoginPageFilterIfNeeded();
|
||||
createUserServiceInjector();
|
||||
createUserDetailsServiceFactory();
|
||||
createExceptionTranslationFilter();
|
||||
|
||||
}
|
||||
|
@ -237,11 +237,12 @@ final class AuthenticationConfigBuilder {
|
|||
BeanDefinitionBuilder openIDProviderBuilder =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
|
||||
|
||||
String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
|
||||
if (StringUtils.hasText(userService)) {
|
||||
openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
|
||||
}
|
||||
openIDProviderBuilder.addPropertyValue("authenticationUserDetailsService", uds);
|
||||
|
||||
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
||||
openIDProviderId = pc.getReaderContext().registerWithGeneratedName(openIDProvider);
|
||||
|
@ -321,14 +322,12 @@ final class AuthenticationConfigBuilder {
|
|||
Element x509Elt = DomUtils.getChildElementByTagName(httpElt, Elements.X509);
|
||||
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
|
||||
|
||||
String userServiceRef = x509Elt.getAttribute(ATT_USER_SERVICE_REF);
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(x509Elt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
|
||||
if (StringUtils.hasText(userServiceRef)) {
|
||||
RootBeanDefinition preAuthUserService = new RootBeanDefinition(UserDetailsByNameServiceWrapper.class);
|
||||
preAuthUserService.setSource(pc.extractSource(x509Elt));
|
||||
preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
|
||||
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", preAuthUserService);
|
||||
}
|
||||
provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds);
|
||||
|
||||
x509ProviderId = pc.getReaderContext().registerWithGeneratedName(provider);
|
||||
x509ProviderRef = new RuntimeBeanReference(x509ProviderId);
|
||||
|
@ -527,14 +526,14 @@ final class AuthenticationConfigBuilder {
|
|||
return (String) pv.getValue();
|
||||
}
|
||||
|
||||
void createUserServiceInjector() {
|
||||
BeanDefinitionBuilder userServiceInjector =
|
||||
BeanDefinitionBuilder.rootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
|
||||
userServiceInjector.addConstructorArgValue(x509ProviderId);
|
||||
userServiceInjector.addConstructorArgValue(rememberMeServicesId);
|
||||
userServiceInjector.addConstructorArgValue(openIDProviderId);
|
||||
userServiceInjector.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
pc.getReaderContext().registerWithGeneratedName(userServiceInjector.getBeanDefinition());
|
||||
private void createUserDetailsServiceFactory() {
|
||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE_FACTORY)) {
|
||||
// Multiple <http> case
|
||||
return;
|
||||
}
|
||||
RootBeanDefinition bean = new RootBeanDefinition(UserDetailsServiceFactoryBean.class);
|
||||
bean.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
pc.getReaderContext().getRegistry().registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_FACTORY, bean);
|
||||
}
|
||||
|
||||
List<OrderDecorator> getFilters() {
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
|
||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
|
||||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
|
||||
|
@ -87,9 +88,12 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
|||
}
|
||||
|
||||
if (services != null) {
|
||||
if (userServiceSet) {
|
||||
services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
|
||||
}
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("cachingUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(userServiceRef);
|
||||
|
||||
services.getPropertyValues().addPropertyValue("userDetailsService", uds);
|
||||
|
||||
if ("true".equals(element.getAttribute(ATT_SECURE_COOKIE))) {
|
||||
services.getPropertyValues().addPropertyValue("useSecureCookie", true);
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
package org.springframework.security.config.http;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.security.config.authentication.AbstractUserDetailsServiceBeanDefinitionParser;
|
||||
import org.springframework.security.config.authentication.CachingUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Bean used to lookup a named UserDetailsService or AuthenticationUserDetailsService.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
*/
|
||||
public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext beanFactory;
|
||||
|
||||
UserDetailsService userDetailsService(String id) {
|
||||
if (!StringUtils.hasText(id)) {
|
||||
return getUserDetailsService();
|
||||
}
|
||||
|
||||
return (UserDetailsService) beanFactory.getBean(id);
|
||||
}
|
||||
|
||||
UserDetailsService cachingUserDetailsService(String id) {
|
||||
if (!StringUtils.hasText(id)) {
|
||||
return getUserDetailsService();
|
||||
}
|
||||
// Overwrite with the caching version if available
|
||||
String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
|
||||
|
||||
if (beanFactory.containsBeanDefinition(cachingId)) {
|
||||
return (UserDetailsService) beanFactory.getBean(cachingId);
|
||||
}
|
||||
|
||||
return (UserDetailsService) beanFactory.getBean(id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
AuthenticationUserDetailsService authenticationUserDetailsService(String name) {
|
||||
UserDetailsService uds;
|
||||
|
||||
if (!StringUtils.hasText(name)) {
|
||||
Map<String,?> beans = getBeansOfType(AuthenticationUserDetailsService.class);
|
||||
|
||||
if (!beans.isEmpty()) {
|
||||
if (beans.size() > 1) {
|
||||
throw new ApplicationContextException("More than one AuthenticationUserDetailsService registered." +
|
||||
"Please use a specific Id reference in <openid-login/> element.");
|
||||
}
|
||||
return (AuthenticationUserDetailsService) beans.values().toArray()[0];
|
||||
}
|
||||
|
||||
uds = getUserDetailsService();
|
||||
} else {
|
||||
Object bean = beanFactory.getBean(name);
|
||||
|
||||
if (bean instanceof AuthenticationUserDetailsService) {
|
||||
return (AuthenticationUserDetailsService)bean;
|
||||
} else if (bean instanceof UserDetailsService) {
|
||||
uds = cachingUserDetailsService(name);
|
||||
|
||||
if (uds == null) {
|
||||
uds = (UserDetailsService)bean;
|
||||
}
|
||||
} else {
|
||||
throw new ApplicationContextException("Bean '" + name + "' must be a UserDetailsService or an" +
|
||||
" AuthenticationUserDetailsService");
|
||||
}
|
||||
}
|
||||
|
||||
return new UserDetailsByNameServiceWrapper(uds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a user details service for use in RememberMeServices etc. Will return a caching version
|
||||
* if available so should not be used for beans which need to separate the two.
|
||||
*/
|
||||
private UserDetailsService getUserDetailsService() {
|
||||
Map<String,?> beans = getBeansOfType(CachingUserDetailsService.class);
|
||||
|
||||
if (beans.size() == 0) {
|
||||
beans = getBeansOfType(UserDetailsService.class);
|
||||
}
|
||||
|
||||
if (beans.size() == 0) {
|
||||
throw new ApplicationContextException("No UserDetailsService registered.");
|
||||
|
||||
} else if (beans.size() > 1) {
|
||||
throw new ApplicationContextException("More than one UserDetailsService registered. Please " +
|
||||
"use a specific Id reference in <remember-me/> <openid-login/> or <x509 /> elements.");
|
||||
}
|
||||
|
||||
return (UserDetailsService) beans.values().toArray()[0];
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
private Map<String,?> getBeansOfType(Class<?> type) {
|
||||
Map<String,?> beans = beanFactory.getBeansOfType(type);
|
||||
|
||||
// Check ancestor bean factories if they exist and the current one has none of the required type
|
||||
BeanFactory parent = beanFactory.getParentBeanFactory();
|
||||
while (parent != null && beans.size() == 0) {
|
||||
if (parent instanceof ListableBeanFactory) {
|
||||
beans = ((ListableBeanFactory)parent).getBeansOfType(type);
|
||||
}
|
||||
if (parent instanceof HierarchicalBeanFactory) {
|
||||
parent = ((HierarchicalBeanFactory)parent).getParentBeanFactory();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return beans;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
package org.springframework.security.config.http;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.security.config.authentication.AbstractUserDetailsServiceBeanDefinitionParser;
|
||||
import org.springframework.security.config.authentication.CachingUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Registered by {@link HttpSecurityBeanDefinitionParser} to inject a UserDetailsService into
|
||||
* the X509Provider, RememberMeServices and OpenIDAuthenticationProvider instances created by
|
||||
* the namespace.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
private final String x509ProviderId;
|
||||
private final String rememberMeServicesId;
|
||||
private final String openIDProviderId;
|
||||
|
||||
public UserDetailsServiceInjectionBeanPostProcessor(String x509ProviderId, String rememberMeServicesId,
|
||||
String openIDProviderId) {
|
||||
this.x509ProviderId = x509ProviderId;
|
||||
this.rememberMeServicesId = rememberMeServicesId;
|
||||
this.openIDProviderId = openIDProviderId;
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if(beanName == null) {
|
||||
return bean;
|
||||
}
|
||||
if (beanName.equals(x509ProviderId)) {
|
||||
injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean);
|
||||
} else if (beanName.equals(rememberMeServicesId)) {
|
||||
injectUserDetailsServiceIntoRememberMeServices(bean);
|
||||
} else if (beanName.equals(openIDProviderId)) {
|
||||
injectUserDetailsServiceIntoOpenIDProvider(bean);
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
private void injectUserDetailsServiceIntoRememberMeServices(Object rms) {
|
||||
if (!(rms instanceof AbstractRememberMeServices)) {
|
||||
logger.info("RememberMeServices is not an instance of AbstractRememberMeServices. UserDetailsService will" +
|
||||
" not be automatically injected.");
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractRememberMeServices services = (AbstractRememberMeServices) rms;
|
||||
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(rememberMeServicesId);
|
||||
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
|
||||
|
||||
if (pv == null) {
|
||||
// If it doesn't already have a UserDetailsService set, then set it.
|
||||
services.setUserDetailsService(getUserDetailsService());
|
||||
} else {
|
||||
// If already set, then attempt to locate a caching version of the injected UserDetailsService
|
||||
UserDetailsService cachingUserService = getCachingUserService(pv.getValue());
|
||||
|
||||
if (cachingUserService != null) {
|
||||
services.setUserDetailsService(cachingUserService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void injectUserDetailsServiceIntoX509Provider(PreAuthenticatedAuthenticationProvider provider) {
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(x509ProviderId);
|
||||
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
|
||||
UserDetailsByNameServiceWrapper wrapper = new UserDetailsByNameServiceWrapper();
|
||||
|
||||
if (pv == null) {
|
||||
wrapper.setUserDetailsService(getUserDetailsService());
|
||||
provider.setPreAuthenticatedUserDetailsService(wrapper);
|
||||
} else {
|
||||
RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue();
|
||||
Object userService =
|
||||
preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue();
|
||||
|
||||
UserDetailsService cachingUserService = getCachingUserService(userService);
|
||||
|
||||
if (cachingUserService != null) {
|
||||
wrapper.setUserDetailsService(cachingUserService);
|
||||
provider.setPreAuthenticatedUserDetailsService(wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void injectUserDetailsServiceIntoOpenIDProvider(Object bean) {
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(openIDProviderId);
|
||||
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
|
||||
|
||||
if (pv == null) {
|
||||
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean);
|
||||
beanWrapper.setPropertyValue("userDetailsService", getUserDetailsService());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a user details service for use in RememberMeServices etc. Will return a caching version
|
||||
* if available so should not be used for beans which need to separate the two.
|
||||
*/
|
||||
UserDetailsService getUserDetailsService() {
|
||||
Map<String,?> beans = getBeansOfType(CachingUserDetailsService.class);
|
||||
|
||||
if (beans.size() == 0) {
|
||||
beans = getBeansOfType(UserDetailsService.class);
|
||||
}
|
||||
|
||||
if (beans.size() == 0) {
|
||||
throw new ApplicationContextException("No UserDetailsService registered.");
|
||||
|
||||
} else if (beans.size() > 1) {
|
||||
throw new ApplicationContextException("More than one UserDetailsService registered. Please " +
|
||||
"use a specific Id reference in <remember-me/> <openid-login/> or <x509 /> elements.");
|
||||
}
|
||||
|
||||
return (UserDetailsService) beans.values().toArray()[0];
|
||||
}
|
||||
|
||||
private UserDetailsService getCachingUserService(Object userServiceRef) {
|
||||
Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef,
|
||||
"userDetailsService property value must be a RuntimeBeanReference");
|
||||
|
||||
String id = ((RuntimeBeanReference)userServiceRef).getBeanName();
|
||||
// Overwrite with the caching version if available
|
||||
String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
|
||||
|
||||
if (beanFactory.containsBeanDefinition(cachingId)) {
|
||||
return (UserDetailsService) beanFactory.getBean(cachingId);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String,?> getBeansOfType(Class<?> type) {
|
||||
Map<String,?> beans = beanFactory.getBeansOfType(type);
|
||||
|
||||
// Check ancestor bean factories if they exist and the current one has none of the required type
|
||||
BeanFactory parent = beanFactory.getParentBeanFactory();
|
||||
while (parent != null && beans.size() == 0) {
|
||||
if (parent instanceof ListableBeanFactory) {
|
||||
beans = ((ListableBeanFactory)parent).getBeansOfType(type);
|
||||
}
|
||||
if (parent instanceof HierarchicalBeanFactory) {
|
||||
parent = ((HierarchicalBeanFactory)parent).getParentBeanFactory();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return beans;
|
||||
}
|
||||
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
package org.springframework.security.core.userdetails;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -49,12 +48,10 @@ public class User implements UserDetails {
|
|||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Calls the more complex constructor with all boolean arguments set to {@code true}.
|
||||
*/
|
||||
public User(String username, String password, boolean enabled, boolean accountNonExpired,
|
||||
boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) {
|
||||
this(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,
|
||||
authorities == null ? null : Arrays.asList(authorities));
|
||||
public User(String username, String password, Collection<GrantedAuthority> authorities) {
|
||||
this(username, password, true, true, true, true, authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,9 @@ import org.springframework.security.authentication.AuthenticationServiceExceptio
|
|||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
@ -29,7 +31,7 @@ import org.springframework.util.Assert;
|
|||
* Finalises the OpenID authentication by obtaining local authorities for the authenticated user.
|
||||
* <p>
|
||||
* The authorities are obtained by calling the configured <tt>UserDetailsService</tt>.
|
||||
* The <code>UserDetails</code> it returns must, at minimum, contain the username and <code>GrantedAuthority[]</code>
|
||||
* The <code>UserDetails</code> it returns must, at minimum, contain the username and <code>GrantedAuthority</code>
|
||||
* objects applicable to the authenticated user. Note that by default, Spring Security ignores the password and
|
||||
* enabled/disabled status of the <code>UserDetails</code> because this is
|
||||
* authentication-related and should have been enforced by another provider server.
|
||||
|
@ -42,7 +44,7 @@ import org.springframework.util.Assert;
|
|||
public class OpenIDAuthenticationProvider implements AuthenticationProvider, InitializingBean {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private UserDetailsService userDetailsService;
|
||||
private AuthenticationUserDetailsService<OpenIDAuthenticationToken> userDetailsService;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
|
@ -66,7 +68,7 @@ public class OpenIDAuthenticationProvider implements AuthenticationProvider, Ini
|
|||
// handle the various possibilities
|
||||
if (status == OpenIDAuthenticationStatus.SUCCESS) {
|
||||
// Lookup user details
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(response.getIdentityUrl());
|
||||
UserDetails userDetails = userDetailsService.loadUserDetails(response);
|
||||
|
||||
return createSuccessfulAuthentication(userDetails, response);
|
||||
|
||||
|
@ -103,9 +105,16 @@ public class OpenIDAuthenticationProvider implements AuthenticationProvider, Ini
|
|||
}
|
||||
|
||||
/**
|
||||
* Used to load the authorities for the authenticated OpenID user.
|
||||
* Used to load the {@code UserDetails} for the authenticated OpenID user.
|
||||
*/
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>(userDetailsService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to load the {@code UserDetails} for the authenticated OpenID user.
|
||||
*/
|
||||
public void setAuthenticationUserDetailsService(AuthenticationUserDetailsService<OpenIDAuthenticationToken> userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
|
|
|
@ -183,17 +183,16 @@ public class OpenIDAuthenticationProviderTests extends TestCase {
|
|||
|
||||
public void testValidation() throws Exception {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
provider.setUserDetailsService(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("IllegalArgumentException expected, ssoAuthoritiesPopulator is null");
|
||||
} catch (IllegalArgumentException e) {
|
||||
//expected
|
||||
}
|
||||
|
||||
provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
provider.afterPropertiesSet();
|
||||
}
|
||||
|
||||
static class MockUserDetailsService implements UserDetailsService {
|
||||
|
|
Loading…
Reference in New Issue