SEC-1657: Added support for 'name' attribute in <http> element to expose filter chain as a list bean.

This commit is contained in:
Luke Taylor 2011-01-14 17:21:22 +00:00
parent f20649f035
commit 2eefbf3a23
5 changed files with 61 additions and 6 deletions

View File

@ -2,6 +2,7 @@ package org.springframework.security.config.http;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
@ -26,8 +27,9 @@ public class HttpFirewallBeanDefinitionParser implements BeanDefinitionParser {
pc.getReaderContext().error("ref attribute is required", pc.extractSource(element));
}
// Ensure the FCP is registered.
HttpSecurityBeanDefinitionParser.registerFilterChainProxy(pc,
new ManagedMap<BeanDefinition, List<BeanMetadataElement>>(),
new ManagedMap<BeanDefinition, BeanReference>(),
pc.extractSource(element));
BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY);
filterChainProxy.getPropertyValues().addPropertyValue("firewall", new RuntimeBeanReference(ref));

View File

@ -10,6 +10,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ListFactoryBean;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
@ -72,7 +73,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
pc.pushContainingComponent(compositeDef);
MatcherType matcherType = MatcherType.fromElement(element);
ManagedMap<BeanDefinition, List<BeanMetadataElement>> filterChainMap = new ManagedMap<BeanDefinition, List<BeanMetadataElement>>();
ManagedMap<BeanDefinition, BeanReference> filterChainMap = new ManagedMap<BeanDefinition, BeanReference>();
String filterChainPattern = element.getAttribute(ATT_PATH_PATTERN);
@ -92,7 +93,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
return null;
}
List<BeanMetadataElement> createFilterChain(Element element, ParserContext pc, MatcherType matcherType) {
BeanReference createFilterChain(Element element, ParserContext pc, MatcherType matcherType) {
boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED));
if (!secured) {
@ -108,7 +109,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
}
return Collections.emptyList();
return createFilterListBean(element, pc, Collections.emptyList());
}
final String portMapperName = createPortMapper(element, pc);
@ -140,9 +141,24 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
filterChain.add(od.bean);
}
return filterChain;
return createFilterListBean(element, pc, filterChain);
}
private BeanReference createFilterListBean(Element element, ParserContext pc, List<?> filterChain) {
BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
String id = element.getAttribute("name");
if (!StringUtils.hasText(id)) {
id = element.getAttribute("id");
if (!StringUtils.hasText(id)) {
id = pc.getReaderContext().generateBeanName(listFactoryBean);
}
}
listFactoryBean.getPropertyValues().add("sourceList", filterChain);
pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, id));
return new RuntimeBeanReference(id);
}
private String createPortMapper(Element elt, ParserContext pc) {
// Register the portMapper. A default will always be created, even if no element exists.
@ -247,7 +263,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
@SuppressWarnings("unchecked")
static void registerFilterChainProxy(ParserContext pc, Map<BeanDefinition, List<BeanMetadataElement>> filterChainMap, Object source) {
static void registerFilterChainProxy(ParserContext pc, Map<BeanDefinition, BeanReference> filterChainMap, Object source) {
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
// Already registered. Obtain the filter chain map and add the new entries to it

View File

@ -25,6 +25,9 @@ url =
id =
## A bean identifier, used for referring to the bean elsewhere in the context.
attribute id {xsd:ID}
name =
## A bean identifier, used for referring to the bean elsewhere in the context.
attribute name {xsd:ID}
ref =
## Defines a reference to a Spring bean Id.
attribute ref {xsd:token}
@ -311,6 +314,10 @@ http.attlist &=
http.attlist &=
## Prevents the jsessionid parameter from being added to rendered URLs.
attribute disable-url-rewriting {xsd:boolean}?
http.attlist &=
## Exposes the list of filters defined by this configuration under this bean name in the application context. May be used by
name?
access-denied-handler =
## Defines the access-denied strategy that should be used. An access denied page can be defined or a reference to an AccessDeniedHandler instance.

View File

@ -70,6 +70,13 @@
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="name">
<xs:attribute name="name" use="required" type="xs:ID">
<xs:annotation>
<xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="ref">
<xs:attribute name="ref" use="required" type="xs:token">
<xs:annotation>
@ -781,6 +788,11 @@
<xs:documentation>Prevents the jsessionid parameter from being added to rendered URLs.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="name" type="xs:ID">
<xs:annotation>
<xs:documentation>A bean identifier, used for referring to the bean elsewhere in the context.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="access-denied-handler.attlist">

View File

@ -3,6 +3,7 @@ package org.springframework.security.config.http
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException
import org.springframework.security.config.BeanIds
import org.springframework.security.web.FilterChainProxy
import org.junit.Assert
/**
* Tests scenarios with multiple &lt;http&gt; elements.
@ -40,4 +41,21 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
then:
thrown(BeanDefinitionParsingException)
}
def namedFilterChainIsExposedAsABean () {
xml.http(name: 'basic', pattern: '/basic/**', 'create-session': 'stateless') {
'http-basic'()
}
xml.http(pattern: '/form/**') {
'form-login'()
}
createAppContext()
def fcp = appContext.getBean(BeanIds.FILTER_CHAIN_PROXY)
List filterChains = fcp.getFilterChainMap().values() as List;
List basicChain = filterChains[0];
expect:
Assert.assertSame (basicChain, appContext.getBean('basic'))
}
}