SEC-271: Impemented FilterSecurityInovation parser for 'authorization-http-url' tag
This commit is contained in:
parent
b1a39fe1d1
commit
97a568c078
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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>
|
Loading…
Reference in New Issue