SEC-271: Impemented FilterSecurityInovation parser for 'authorization-http-url' tag

This commit is contained in:
Vishal Puri 2007-07-04 05:04:26 +00:00
parent b1a39fe1d1
commit 97a568c078
3 changed files with 267 additions and 0 deletions

View File

@ -0,0 +1,170 @@
package org.acegisecurity.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionDecorator;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionSourceMapping;
import org.acegisecurity.intercept.web.FilterSecurityInterceptor;
import org.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap;
import org.acegisecurity.intercept.web.RegExpBasedFilterInvocationDefinitionMap;
import org.acegisecurity.util.BeanDefinitionParserUtils;
import org.acegisecurity.vote.AffirmativeBased;
import org.acegisecurity.vote.AuthenticatedVoter;
import org.acegisecurity.vote.RoleVoter;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* @author Vishal Puri
*
*/
public class FilterSecurityInterceptorBeanDefinitionParser extends AbstractBeanDefinitionParser {
private static final String OBJECT_DEFINITION_SOURCE_PROPERTY = "objectDefinitionSource";
private static final String OBJECT_DEFINITION_SOURCE_REF_ATTRIBUTE = "sourceBeanId";
private static final String PATH_ATTRIBUTE = "path";
private static final String REG_EX_ATTRIBUTE = "regularExpression";
private static final String CONFIGURATION_ATTRIB_ATTRIBUTE = "attribute";
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
return createBeanDefinitionForFilterSecurityInterceptor(element, parserContext);
}
protected static RootBeanDefinition createBeanDefinitionForFilterSecurityInterceptor(Element element,
ParserContext parserContext) {
RootBeanDefinition filterInvocationInterceptor = new RootBeanDefinition(FilterSecurityInterceptor.class);
RootBeanDefinition accessDecisionManager = createAccessDecisionManagerAffirmativeBased();
filterInvocationInterceptor.getPropertyValues()
.addPropertyValue("accessDecisionManager", accessDecisionManager);
FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator();
FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping();
List<FilterInvocationDefinitionSourceMapping> mappings = new ArrayList<FilterInvocationDefinitionSourceMapping>();
Element firstChild = DomUtils.getChildElementByTagName(element, "url-mapping");
// if 'url-mapping' element is defined
if (firstChild != null) {
BeanDefinitionParserUtils.setPropertyIfAvailable(firstChild, OBJECT_DEFINITION_SOURCE_REF_ATTRIBUTE,
OBJECT_DEFINITION_SOURCE_PROPERTY, true/* RuntimeBeanReference */, filterInvocationInterceptor);
// get 'uri-pattern' or 'path' attribute. not both can be specified
// together
List uriPatternElements = DomUtils.getChildElementsByTagName(firstChild, "uri-pattern");
boolean patternToMatchCreated = false;
Node patternAttribute = null;
String url = "";
boolean isPathFound = false;
for (Iterator it = uriPatternElements.iterator(); it.hasNext();) {
Element uriPattern = (Element) it.next();
/* path or pattern - only one attribute is allowed */
NamedNodeMap map = uriPattern.getAttributes();
Assert.isTrue(map.getLength() == 1,
"only 'path' or 'regularExperssion' attribute allowed with 'uri-pattern' tag");
// check if typecreated variable is false then create a type and
// store it somewhere and set typecreated variable to true
if (!patternToMatchCreated) {
// should only be one attribute "path" or
// "regularExpression"
patternAttribute = map.item(0);
// set this variable to true
patternToMatchCreated = true;
// get the attributes and set the decoratd type
// appropriately
if (uriPattern.hasAttribute(PATH_ATTRIBUTE)) {
isPathFound = true;
url = uriPattern.getAttribute(PATH_ATTRIBUTE);
source.setDecorated(new PathBasedFilterInvocationDefinitionMap());
}
else if (uriPattern.hasAttribute(REG_EX_ATTRIBUTE)) {
url = uriPattern.getAttribute(REG_EX_ATTRIBUTE);
source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
}
}
else {
// type created already so check if it matches with the
// current element
// if it matches get the one attribute "path" or
// "regularExpression" and apply as property
uriPattern.getAttribute(patternAttribute.getLocalName());
Assert
.hasLength(uriPattern.getAttribute(patternAttribute.getLocalName()),
" ALL uri-pattern tags in the url-mapping must be of the same type (ie cannot mix a regular expression and Ant Path)");
if (isPathFound) {
url = uriPattern.getAttribute(PATH_ATTRIBUTE);
}
else {
url = uriPattern.getAttribute(REG_EX_ATTRIBUTE);
}
}
mapping.setUrl(url);
// get child elements 'configuration-attribute'
List configAttributes = DomUtils.getChildElementsByTagName(uriPattern, "configuration-attribute");
for (Iterator iter = configAttributes.iterator(); iter.hasNext();) {
Element configAttribute = (Element) iter.next();
String configAttributeValue = configAttribute.getAttribute(CONFIGURATION_ATTRIB_ATTRIBUTE);
mapping.addConfigAttribute(configAttributeValue);
}
}
}
// default properties
else {
String url1 = "/acegilogin.jsp";
String value1 = "IS_AUTHENTICATED_ANONYMOUSLY";
String url2 = "/**";
String value2 = "IS_AUTHENTICATED_REMEMBERED";
mapping.setUrl(url1);
mapping.addConfigAttribute(value1);
mapping.setUrl(url2);
mapping.addConfigAttribute(value2);
}
mappings.add(mapping);
source.setMappings(mappings);
filterInvocationInterceptor.getPropertyValues().addPropertyValue("objectDefinitionSource",
source.getDecorated());
return filterInvocationInterceptor;
}
protected static RootBeanDefinition createAccessDecisionManagerAffirmativeBased() {
ManagedList decisionVoters = new ManagedList();
RootBeanDefinition accessDecisionManager = new RootBeanDefinition(AffirmativeBased.class);
accessDecisionManager.getPropertyValues().addPropertyValue("allowIfAllAbstainDecisions", Boolean.FALSE);
RootBeanDefinition authenticatedVoter = new RootBeanDefinition(AuthenticatedVoter.class);
RootBeanDefinition roleVoter = new RootBeanDefinition(RoleVoter.class);
decisionVoters.add(authenticatedVoter);
decisionVoters.add(roleVoter);
accessDecisionManager.getPropertyValues().addPropertyValue("decisionVoters", decisionVoters);
return accessDecisionManager;
}
}

View File

@ -0,0 +1,35 @@
package org.acegisecurity.config;
import junit.framework.TestCase;
import org.acegisecurity.AccessDecisionManager;
import org.acegisecurity.intercept.web.FilterSecurityInterceptor;
import org.acegisecurity.intercept.web.RegExpBasedFilterInvocationDefinitionMap;
import org.acegisecurity.vote.AffirmativeBased;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Vishal Puri
*/
public class FilterSecurityInterceptorBeanDefinitionParserTests extends TestCase {
public void testParsingBeanDefinition() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"org/acegisecurity/config/authorization-http-config.xml");
ConfigurableListableBeanFactory bf = (ConfigurableListableBeanFactory) context.getAutowireCapableBeanFactory();
String[] beanNames = bf.getBeanNamesForType(FilterSecurityInterceptor.class);
assertEquals(1, beanNames.length);
BeanDefinition def = bf.getBeanDefinition(beanNames[0]);
assertEquals(2, def.getPropertyValues().size());
PropertyValue objectDefinitionSource = def.getPropertyValues().getPropertyValue("objectDefinitionSource");
assertTrue(objectDefinitionSource.getValue() instanceof RegExpBasedFilterInvocationDefinitionMap);
PropertyValue accessDecisionManager = def.getPropertyValues().getPropertyValue("accessDecisionManager");
BeanDefinition definition = (RootBeanDefinition) accessDecisionManager.getValue() ;
assertEquals("org.acegisecurity.vote.AffirmativeBased" , definition.getBeanClassName());
}
}

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!-- ensure element name is not overlapping with portlet or spring web flow or tapestry URI patterns,
as this filter is incompatible with them -->
<import resource="remember-me-defaults.xml" />
<security:authorization-http-url id="authorizationhttp">
<security:url-mapping
source="xml - the default and no other options"
sourceBeanId="referenceToTheirObjectDefinitionSource">
<!-- Specify security:uri-patterns in order of processing; each pattern must specify EITHER a
regularExpression OR a path, but not both and ALL patterns in the url-mapping MUST be of the
SAME type (ie cannot mix a regular expression and Ant Path) - give exception if tried -->
<security:uri-pattern regularExpression="/**">
<security:configuration-attribute attribute="ROLE_A" />
<security:configuration-attribute attribute="ROLE_B" />
</security:uri-pattern>
<security:uri-pattern
regularExpression="whatever">
<security:configuration-attribute attribute="ROLE_A" />
</security:uri-pattern>
</security:url-mapping>
</security:authorization-http-url>
<!--<bean id="filterInvocationInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager"
ref="authenticationManager" />
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions"
value="false" />
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter" />
<bean
class="org.acegisecurity.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp=IS_AUTHENTICATED_ANONYMOUSLY
/**=IS_AUTHENTICATED_REMEMBERED
</value>
</property>
</bean>
-->
</beans>