SEC-1263: Add FactoryBean for namespace AuthenticationManager. <http> now uses AuthenticationManagerFactoryBean. Method security already uses a delegate object to lookup the AuthenticationManager. This now uses the same error message if the bean isn't found, rather than allowing the BeanFactory NoSuchBeanDefinitionException to be thrown directly.
This commit is contained in:
parent
ac5237c127
commit
ed2ddf9323
|
@ -9,7 +9,7 @@ package org.springframework.security.config;
|
||||||
* @version $Id: BeanIds.java 3770 2009-07-15 23:09:47Z ltaylor $
|
* @version $Id: BeanIds.java 3770 2009-07-15 23:09:47Z ltaylor $
|
||||||
*/
|
*/
|
||||||
public abstract class BeanIds {
|
public abstract class BeanIds {
|
||||||
private static final String PREFIX = "org.springframework.security";
|
private static final String PREFIX = "org.springframework.security.";
|
||||||
|
|
||||||
/** The "global" AuthenticationManager instance, registered by the <authentication-manager> element */
|
/** The "global" AuthenticationManager instance, registered by the <authentication-manager> element */
|
||||||
public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager";
|
public static final String AUTHENTICATION_MANAGER = PREFIX + "authenticationManager";
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.springframework.security.config.authentication;
|
package org.springframework.security.config.authentication;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
|
@ -21,17 +19,18 @@ import org.springframework.security.config.BeanIds;
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
|
public class AuthenticationManagerFactoryBean implements FactoryBean<AuthenticationManager>, BeanFactoryAware {
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
|
||||||
private BeanFactory bf;
|
private BeanFactory bf;
|
||||||
|
public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add an <authentication-manager> element " +
|
||||||
|
"to your configuration (with child <authentication-provider> elements) ?";
|
||||||
|
|
||||||
public AuthenticationManager getObject() throws Exception {
|
public AuthenticationManager getObject() throws Exception {
|
||||||
try {
|
try {
|
||||||
return (AuthenticationManager) bf.getBean(BeanIds.AUTHENTICATION_MANAGER);
|
return (AuthenticationManager) bf.getBean(BeanIds.AUTHENTICATION_MANAGER);
|
||||||
} catch (NoSuchBeanDefinitionException e) {
|
} catch (NoSuchBeanDefinitionException e) {
|
||||||
logger.error(BeanIds.AUTHENTICATION_MANAGER + " bean was not found in the application context.");
|
if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
|
||||||
throw new NoSuchBeanDefinitionException("The namespace AuthenticationManager was not found. " +
|
throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, MISSING_BEAN_ERROR_MESSAGE);
|
||||||
"Did you forget to add an <authentication-manager> element to your configuration with " +
|
}
|
||||||
"child <authentication-provider> elements ?");
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.springframework.beans.BeanMetadataElement;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.BeanReference;
|
import org.springframework.beans.factory.config.BeanReference;
|
||||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
@ -48,6 +49,7 @@ import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.ProviderManager;
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
import org.springframework.security.config.BeanIds;
|
import org.springframework.security.config.BeanIds;
|
||||||
import org.springframework.security.config.Elements;
|
import org.springframework.security.config.Elements;
|
||||||
|
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -77,7 +79,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
||||||
private static final String ATT_REF = "ref";
|
private static final String ATT_REF = "ref";
|
||||||
private static final String ATT_ADVICE_ORDER = "order";
|
private static final String ATT_ADVICE_ORDER = "order";
|
||||||
|
|
||||||
// @SuppressWarnings("unchecked")
|
|
||||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||||
CompositeComponentDefinition compositeDef =
|
CompositeComponentDefinition compositeDef =
|
||||||
new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
|
new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
|
||||||
|
@ -287,7 +288,6 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
||||||
String runAsManagerId, BeanReference metadataSource, List<BeanMetadataElement> afterInvocationProviders, Object source) {
|
String runAsManagerId, BeanReference metadataSource, List<BeanMetadataElement> afterInvocationProviders, Object source) {
|
||||||
BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class);
|
BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class);
|
||||||
bldr.getRawBeanDefinition().setSource(source);
|
bldr.getRawBeanDefinition().setSource(source);
|
||||||
|
|
||||||
bldr.addPropertyReference("accessDecisionManager", accessManagerId);
|
bldr.addPropertyReference("accessDecisionManager", accessManagerId);
|
||||||
bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
|
bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
|
||||||
bldr.addPropertyValue("securityMetadataSource", metadataSource);
|
bldr.addPropertyValue("securityMetadataSource", metadataSource);
|
||||||
|
@ -335,7 +335,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware {
|
static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware {
|
||||||
private AuthenticationManager delegate;
|
private AuthenticationManager delegate;
|
||||||
private final Object delegateMonitor = new Object();
|
private final Object delegateMonitor = new Object();
|
||||||
private BeanFactory beanFactory;
|
private BeanFactory beanFactory;
|
||||||
|
@ -344,7 +344,15 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
||||||
synchronized(delegateMonitor) {
|
synchronized(delegateMonitor) {
|
||||||
if (delegate == null) {
|
if (delegate == null) {
|
||||||
Assert.state(beanFactory != null, "BeanFactory must be set to resolve " + BeanIds.AUTHENTICATION_MANAGER);
|
Assert.state(beanFactory != null, "BeanFactory must be set to resolve " + BeanIds.AUTHENTICATION_MANAGER);
|
||||||
|
try {
|
||||||
delegate = beanFactory.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
delegate = beanFactory.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||||
|
} catch (NoSuchBeanDefinitionException e) {
|
||||||
|
if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) {
|
||||||
|
throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER,
|
||||||
|
AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException;
|
import org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException;
|
||||||
|
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
|
||||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +34,23 @@ public class InvalidConfigurationTests {
|
||||||
setContext("<password-encoder hash='md5'/>");
|
setContext("<password-encoder hash='md5'/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected=XmlBeanDefinitionStoreException.class)
|
||||||
|
public void authenticationProviderCannotAppearAtTopLevel() {
|
||||||
|
setContext("<authentication-provider ref='blah'/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void missingAuthenticationManagerGivesSensibleErrorMessage() {
|
||||||
|
try {
|
||||||
|
setContext("<http auto-config='true' />");
|
||||||
|
} catch (BeanCreationException e) {
|
||||||
|
assertTrue(e.getCause().getCause() instanceof NoSuchBeanDefinitionException);
|
||||||
|
NoSuchBeanDefinitionException nsbe = (NoSuchBeanDefinitionException) e.getCause().getCause();
|
||||||
|
assertEquals(BeanIds.AUTHENTICATION_MANAGER, nsbe.getBeanName());
|
||||||
|
assertTrue(nsbe.getMessage().endsWith(AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setContext(String context) {
|
private void setContext(String context) {
|
||||||
appContext = new InMemoryXmlApplicationContext(context);
|
appContext = new InMemoryXmlApplicationContext(context);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue