3 changed files with 267 additions and 0 deletions
@ -0,0 +1,170 @@
@@ -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 @@
@@ -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 @@
@@ -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