1
0
mirror of synced 2026-08-06 10:18:52 +00:00

Support configuration via Apache Ant paths (not only regular expressions).

This commit is contained in:
Ben Alex
2004-04-09 09:51:23 +00:00
parent 5488bf4ca8
commit bd35a47233
11 changed files with 907 additions and 187 deletions
@@ -17,164 +17,19 @@ package net.sf.acegisecurity.intercept.web;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
/**
* Maintains a <Code>List</code> of <code>ConfigAttributeDefinition</code>s
* associated with different HTTP request URL patterns.
*
* <P>
* Regular expressions are used to match a HTTP request URL against a
* <code>ConfigAttributeDefinition</code>.
* </p>
*
* <p>
* The order of registering the regular expressions using the {@link
* #addSecureUrl(String, ConfigAttributeDefinition)} is very important. The
* system will identify the <B>first</B> matching regular expression for a
* given HTTP URL. It will not proceed to evaluate later regular expressions
* if a match has already been found. Accordingly, the most specific regular
* expressions should be registered first, with the most general regular
* expressions registered last.
* </p>
*
* <P>
* If no registered regular expressions match the HTTP URL, <code>null</code>
* is returned.
* </p>
* Exposes methods required so that a property editor can populate the relevant
* {@link FilterInvocationDefinitionSource}.
*
* @author Ben Alex
* @version $Id$
*/
public class FilterInvocationDefinitionMap
extends AbstractFilterInvocationDefinitionSource {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(FilterInvocationDefinitionMap.class);
//~ Instance fields ========================================================
private List requestMap = new Vector();
private boolean convertUrlToLowercaseBeforeComparison = false;
public interface FilterInvocationDefinitionMap {
//~ Methods ================================================================
public Iterator getConfigAttributeDefinitions() {
Set set = new HashSet();
Iterator iter = requestMap.iterator();
while (iter.hasNext()) {
EntryHolder entryHolder = (EntryHolder) iter.next();
set.add(entryHolder.getConfigAttributeDefinition());
}
return set.iterator();
}
public void setConvertUrlToLowercaseBeforeComparison(
boolean convertUrlToLowercaseBeforeComparison) {
this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
}
boolean convertUrlToLowercaseBeforeComparison);
public boolean isConvertUrlToLowercaseBeforeComparison() {
return convertUrlToLowercaseBeforeComparison;
}
public int getMapSize() {
return this.requestMap.size();
}
public void addSecureUrl(String perl5RegExp, ConfigAttributeDefinition attr) {
Pattern compiledPattern;
Perl5Compiler compiler = new Perl5Compiler();
try {
compiledPattern = compiler.compile(perl5RegExp,
Perl5Compiler.READ_ONLY_MASK);
} catch (MalformedPatternException mpe) {
throw new IllegalArgumentException("Malformed regular expression: "
+ perl5RegExp);
}
requestMap.add(new EntryHolder(compiledPattern, attr));
if (logger.isDebugEnabled()) {
logger.debug("Added regular expression: "
+ compiledPattern.getPattern().toString() + "; attributes: "
+ attr.toString());
}
}
protected ConfigAttributeDefinition lookupAttributes(
FilterInvocation filterInvocation) {
PatternMatcher matcher = new Perl5Matcher();
Iterator iter = requestMap.iterator();
String url = filterInvocation.getRequestUrl();
if (convertUrlToLowercaseBeforeComparison) {
url = url.toLowerCase();
if (logger.isDebugEnabled()) {
logger.debug("Converted URL to lowercase, from: '"
+ filterInvocation.getRequest() + "'; to: '" + url + "'");
}
}
while (iter.hasNext()) {
EntryHolder entryHolder = (EntryHolder) iter.next();
boolean matched = matcher.matches(url,
entryHolder.getCompiledPattern());
if (logger.isDebugEnabled()) {
logger.debug("Candidate is: '" + url + "'; pattern is "
+ entryHolder.getCompiledPattern().getPattern()
+ "; matched=" + matched);
}
if (matched) {
return entryHolder.getConfigAttributeDefinition();
}
}
return null;
}
//~ Inner Classes ==========================================================
protected class EntryHolder {
private ConfigAttributeDefinition configAttributeDefinition;
private Pattern compiledPattern;
public EntryHolder(Pattern compiledPattern,
ConfigAttributeDefinition attr) {
this.compiledPattern = compiledPattern;
this.configAttributeDefinition = attr;
}
protected EntryHolder() {
throw new IllegalArgumentException("Cannot use default constructor");
}
public Pattern getCompiledPattern() {
return compiledPattern;
}
public ConfigAttributeDefinition getConfigAttributeDefinition() {
return configAttributeDefinition;
}
}
public void addSecureUrl(String expression, ConfigAttributeDefinition attr);
}
@@ -31,11 +31,21 @@ import java.io.StringReader;
/**
* Property editor to assist with the setup of {@link
* Property editor to assist with the setup of a {@link
* FilterInvocationDefinitionSource}.
*
* <p>
* The class creates and populates a {@link FilterInvocationDefinitionMap}.
* The class creates and populates a {@link
* RegExpBasedFilterInvocationDefinitionMap} or {@link
* PathBasedFilterInvocationDefinitionMap} (depending on the type of patterns
* presented).
* </p>
*
* <P>
* By default the class treats presented patterns as regular expressions. If
* the keyword <code>PATTERN_TYPE_APACHE_ANT</code> is present (case
* sensitive), patterns will be treated as Apache Ant paths rather than
* regular expressions.
* </p>
*
* @author Ben Alex
@@ -50,11 +60,20 @@ public class FilterInvocationDefinitionSourceEditor
//~ Methods ================================================================
public void setAsText(String s) throws IllegalArgumentException {
FilterInvocationDefinitionMap source = new FilterInvocationDefinitionMap();
FilterInvocationDefinitionMap source = new RegExpBasedFilterInvocationDefinitionMap();
if ((s == null) || "".equals(s)) {
// Leave value in property editor null
// Leave target object empty
} else {
// Check if we need to override the default definition map
if (s.lastIndexOf("PATTERN_TYPE_APACHE_ANT") != -1) {
source = new PathBasedFilterInvocationDefinitionMap();
if (logger.isDebugEnabled()) {
logger.debug(("Detected PATTERN_TYPE_APACHE_ANT directive; using Apache Ant style path expressions"));
}
}
BufferedReader br = new BufferedReader(new StringReader(s));
int counter = 0;
String line;
@@ -0,0 +1,158 @@
/* Copyright 2004 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.intercept.web;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.PathMatcher;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
/**
* Maintains a <Code>List</code> of <code>ConfigAttributeDefinition</code>s
* associated with different HTTP request URL Apache Ant path-based patterns.
*
* <P>
* Apache Ant path expressions are used to match a HTTP request URL against a
* <code>ConfigAttributeDefinition</code>.
* </p>
*
* <p>
* The order of registering the Ant paths using the {@link
* #addSecureUrl(String, ConfigAttributeDefinition)} is very important. The
* system will identify the <B>first</B> matching path for a given HTTP URL.
* It will not proceed to evaluate later paths if a match has already been
* found. Accordingly, the most specific paths should be registered first,
* with the most general paths registered last.
* </p>
*
* <P>
* If no registered paths match the HTTP URL, <code>null</code> is returned.
* </p>
*/
public class PathBasedFilterInvocationDefinitionMap
extends AbstractFilterInvocationDefinitionSource
implements FilterInvocationDefinitionMap {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(PathBasedFilterInvocationDefinitionMap.class);
//~ Instance fields ========================================================
private List requestMap = new Vector();
private boolean convertUrlToLowercaseBeforeComparison = false;
//~ Methods ================================================================
public Iterator getConfigAttributeDefinitions() {
Set set = new HashSet();
Iterator iter = requestMap.iterator();
while (iter.hasNext()) {
EntryHolder entryHolder = (EntryHolder) iter.next();
set.add(entryHolder.getConfigAttributeDefinition());
}
return set.iterator();
}
public void setConvertUrlToLowercaseBeforeComparison(
boolean convertUrlToLowercaseBeforeComparison) {
this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
}
public boolean isConvertUrlToLowercaseBeforeComparison() {
return convertUrlToLowercaseBeforeComparison;
}
public int getMapSize() {
return this.requestMap.size();
}
public void addSecureUrl(String antPath, ConfigAttributeDefinition attr) {
requestMap.add(new EntryHolder(antPath, attr));
if (logger.isDebugEnabled()) {
logger.debug("Added Ant path: " + antPath + "; attributes: "
+ attr.toString());
}
}
protected ConfigAttributeDefinition lookupAttributes(
FilterInvocation filterInvocation) {
Iterator iter = requestMap.iterator();
String url = filterInvocation.getRequestUrl();
if (convertUrlToLowercaseBeforeComparison) {
url = url.toLowerCase();
if (logger.isDebugEnabled()) {
logger.debug("Converted URL to lowercase, from: '"
+ filterInvocation.getRequest() + "'; to: '" + url + "'");
}
}
while (iter.hasNext()) {
EntryHolder entryHolder = (EntryHolder) iter.next();
boolean matched = PathMatcher.match(entryHolder.getAntPath(), url);
if (logger.isDebugEnabled()) {
logger.debug("Candidate is: '" + url + "'; pattern is "
+ entryHolder.getAntPath() + "; matched=" + matched);
}
if (matched) {
return entryHolder.getConfigAttributeDefinition();
}
}
return null;
}
//~ Inner Classes ==========================================================
protected class EntryHolder {
private ConfigAttributeDefinition configAttributeDefinition;
private String antPath;
public EntryHolder(String antPath, ConfigAttributeDefinition attr) {
this.antPath = antPath;
this.configAttributeDefinition = attr;
}
protected EntryHolder() {
throw new IllegalArgumentException("Cannot use default constructor");
}
public String getAntPath() {
return antPath;
}
public ConfigAttributeDefinition getConfigAttributeDefinition() {
return configAttributeDefinition;
}
}
}
@@ -0,0 +1,181 @@
/* Copyright 2004 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.intercept.web;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
/**
* Maintains a <Code>List</code> of <code>ConfigAttributeDefinition</code>s
* associated with different HTTP request URL regular expression patterns.
*
* <P>
* Regular expressions are used to match a HTTP request URL against a
* <code>ConfigAttributeDefinition</code>.
* </p>
*
* <p>
* The order of registering the regular expressions using the {@link
* #addSecureUrl(String, ConfigAttributeDefinition)} is very important. The
* system will identify the <B>first</B> matching regular expression for a
* given HTTP URL. It will not proceed to evaluate later regular expressions
* if a match has already been found. Accordingly, the most specific regular
* expressions should be registered first, with the most general regular
* expressions registered last.
* </p>
*
* <P>
* If no registered regular expressions match the HTTP URL, <code>null</code>
* is returned.
* </p>
*/
public class RegExpBasedFilterInvocationDefinitionMap
extends AbstractFilterInvocationDefinitionSource
implements FilterInvocationDefinitionMap {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(RegExpBasedFilterInvocationDefinitionMap.class);
//~ Instance fields ========================================================
private List requestMap = new Vector();
private boolean convertUrlToLowercaseBeforeComparison = false;
//~ Methods ================================================================
public Iterator getConfigAttributeDefinitions() {
Set set = new HashSet();
Iterator iter = requestMap.iterator();
while (iter.hasNext()) {
EntryHolder entryHolder = (EntryHolder) iter.next();
set.add(entryHolder.getConfigAttributeDefinition());
}
return set.iterator();
}
public void setConvertUrlToLowercaseBeforeComparison(
boolean convertUrlToLowercaseBeforeComparison) {
this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
}
public boolean isConvertUrlToLowercaseBeforeComparison() {
return convertUrlToLowercaseBeforeComparison;
}
public int getMapSize() {
return this.requestMap.size();
}
public void addSecureUrl(String perl5RegExp, ConfigAttributeDefinition attr) {
Pattern compiledPattern;
Perl5Compiler compiler = new Perl5Compiler();
try {
compiledPattern = compiler.compile(perl5RegExp,
Perl5Compiler.READ_ONLY_MASK);
} catch (MalformedPatternException mpe) {
throw new IllegalArgumentException("Malformed regular expression: "
+ perl5RegExp);
}
requestMap.add(new EntryHolder(compiledPattern, attr));
if (logger.isDebugEnabled()) {
logger.debug("Added regular expression: "
+ compiledPattern.getPattern().toString() + "; attributes: "
+ attr.toString());
}
}
protected ConfigAttributeDefinition lookupAttributes(
FilterInvocation filterInvocation) {
PatternMatcher matcher = new Perl5Matcher();
Iterator iter = requestMap.iterator();
String url = filterInvocation.getRequestUrl();
if (convertUrlToLowercaseBeforeComparison) {
url = url.toLowerCase();
if (logger.isDebugEnabled()) {
logger.debug("Converted URL to lowercase, from: '"
+ filterInvocation.getRequest() + "'; to: '" + url + "'");
}
}
while (iter.hasNext()) {
EntryHolder entryHolder = (EntryHolder) iter.next();
boolean matched = matcher.matches(url,
entryHolder.getCompiledPattern());
if (logger.isDebugEnabled()) {
logger.debug("Candidate is: '" + url + "'; pattern is "
+ entryHolder.getCompiledPattern().getPattern()
+ "; matched=" + matched);
}
if (matched) {
return entryHolder.getConfigAttributeDefinition();
}
}
return null;
}
//~ Inner Classes ==========================================================
protected class EntryHolder {
private ConfigAttributeDefinition configAttributeDefinition;
private Pattern compiledPattern;
public EntryHolder(Pattern compiledPattern,
ConfigAttributeDefinition attr) {
this.compiledPattern = compiledPattern;
this.configAttributeDefinition = attr;
}
protected EntryHolder() {
throw new IllegalArgumentException("Cannot use default constructor");
}
public Pattern getCompiledPattern() {
return compiledPattern;
}
public ConfigAttributeDefinition getConfigAttributeDefinition() {
return configAttributeDefinition;
}
}
}
@@ -28,7 +28,7 @@ import java.util.Iterator;
/**
* Tests {@link FilterInvocationDefinitionSourceEditor} and its associated
* {@link FilterInvocationDefinitionMap}.
* default {@link RegExpBasedFilterInvocationDefinitionMap}.
*
* @author Ben Alex
* @version $Id$
@@ -59,7 +59,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
editor.setAsText(
"\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
}
@@ -69,16 +69,26 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
editor.setAsText(
"CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
}
public void testDefaultIsRegularExpression() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
.getValue();
assertTrue(map instanceof RegExpBasedFilterInvocationDefinitionMap);
}
public void testEmptyStringReturnsEmptyMap() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText("");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
assertEquals(0, map.getMapSize());
}
@@ -100,7 +110,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
editor.setAsText(
"\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
Iterator iter = map.getConfigAttributeDefinitions();
int counter = 0;
@@ -117,7 +127,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
@@ -136,14 +146,14 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
editor.setAsText(
"\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
assertEquals(2, map.getMapSize());
}
public void testNoArgsConstructor() {
try {
new FilterInvocationDefinitionMap().new EntryHolder();
new RegExpBasedFilterInvocationDefinitionMap().new EntryHolder();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
@@ -154,7 +164,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(null);
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
assertEquals(0, map.getMapSize());
}
@@ -164,7 +174,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
editor.setAsText(
"\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
// Test ensures we match the first entry, not the second
@@ -188,7 +198,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
editor.setAsText(
"\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
@@ -210,7 +220,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
@@ -233,7 +243,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
editor.setAsText(
" \\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE \r\n \r\n \r\n // comment line \r\n \\A/testing.*\\Z=ROLE_TEST \r\n");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
RegExpBasedFilterInvocationDefinitionMap map = (RegExpBasedFilterInvocationDefinitionMap) editor
.getValue();
assertEquals(2, map.getMapSize());
}
@@ -0,0 +1,223 @@
/* Copyright 2004 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.intercept.web;
import junit.framework.TestCase;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.MockFilterChain;
import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.SecurityConfig;
import java.util.Iterator;
/**
* Tests {@link FilterInvocationDefinitionSourceEditor} and its associated
* {@link PathBasedFilterInvocationDefinitionMap}.
*
* @author Ben Alex
* @version $Id$
*/
public class FilterInvocationDefinitionSourceEditorWithPathsTests
extends TestCase {
//~ Constructors ===========================================================
public FilterInvocationDefinitionSourceEditorWithPathsTests() {
super();
}
public FilterInvocationDefinitionSourceEditorWithPathsTests(String arg0) {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(FilterInvocationDefinitionSourceEditorWithPathsTests.class);
}
public void testAntPathDirectiveIsDetected() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER");
FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
.getValue();
assertTrue(map instanceof PathBasedFilterInvocationDefinitionMap);
}
public void testConvertUrlToLowercaseDefaultSettingUnchangedByEditor() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
}
public void testConvertUrlToLowercaseSettingApplied() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\nPATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
}
public void testIterator() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
Iterator iter = map.getConfigAttributeDefinitions();
int counter = 0;
while (iter.hasNext()) {
iter.next();
counter++;
}
assertEquals(2, counter);
}
public void testMapReturnsNullWhenNoMatchFound() throws Exception {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
null);
httpRequest.setServletPath("/totally/different/path/index.html");
ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
httpRequest, new MockHttpServletResponse(),
new MockFilterChain()));
assertEquals(null, returned);
}
public void testMultiUrlParsing() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE\r\n/secure/*=ROLE_SUPERVISOR,ROLE_TELLER");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
assertEquals(2, map.getMapSize());
}
public void testNoArgsConstructor() {
try {
new PathBasedFilterInvocationDefinitionMap().new EntryHolder();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testOrderOfEntriesIsPreservedOrderA() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/super/**=ROLE_WE_DONT_HAVE,ANOTHER_ROLE\r\n/secure/**=ROLE_SUPERVISOR,ROLE_TELLER");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
// Test ensures we match the first entry, not the second
MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
null);
httpRequest.setServletPath("/secure/super/very_secret.html");
ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
httpRequest, new MockHttpServletResponse(),
new MockFilterChain()));
ConfigAttributeDefinition expected = new ConfigAttributeDefinition();
expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE"));
expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE"));
assertEquals(expected, returned);
}
public void testOrderOfEntriesIsPreservedOrderB() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/**=ROLE_SUPERVISOR,ROLE_TELLER\r\n/secure/super/**=ROLE_WE_DONT_HAVE");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
null);
httpRequest.setServletPath("/secure/super/very_secret.html");
ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
httpRequest, new MockHttpServletResponse(),
new MockFilterChain()));
ConfigAttributeDefinition expected = new ConfigAttributeDefinition();
expected.addConfigAttribute(new SecurityConfig("ROLE_SUPERVISOR"));
expected.addConfigAttribute(new SecurityConfig("ROLE_TELLER"));
assertEquals(expected, returned);
}
public void testSingleUrlParsing() throws Exception {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
"PATTERN_TYPE_APACHE_ANT\r\n/secure/super/*=ROLE_WE_DONT_HAVE,ANOTHER_ROLE");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
null);
httpRequest.setServletPath("/secure/super/very_secret.html");
ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
httpRequest, new MockHttpServletResponse(),
new MockFilterChain()));
ConfigAttributeDefinition expected = new ConfigAttributeDefinition();
expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE"));
expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE"));
assertEquals(expected, returned);
}
public void testWhitespaceAndCommentsAndLinesWithoutEqualsSignsAreIgnored() {
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
editor.setAsText(
" PATTERN_TYPE_APACHE_ANT\r\n /secure/super/*=ROLE_WE_DONT_HAVE\r\n /secure/*=ROLE_SUPERVISOR,ROLE_TELLER \r\n \r\n \r\n // comment line \r\n \r\n");
PathBasedFilterInvocationDefinitionMap map = (PathBasedFilterInvocationDefinitionMap) editor
.getValue();
assertEquals(2, map.getMapSize());
}
}
@@ -48,7 +48,7 @@ import javax.servlet.ServletResponse;
/**
* Tests {@link FiltSecurityInterceptor}.
* Tests {@link FilterSecurityInterceptor}.
*
* @author Ben Alex
* @version $Id$
@@ -77,7 +77,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
public void testEnsuresAccessDecisionManagerSupportsFilterInvocationClass() {
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setAuthenticationManager(new MockAuthenticationManager());
interceptor.setObjectDefinitionSource(new FilterInvocationDefinitionMap());
interceptor.setObjectDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
interceptor.setRunAsManager(new MockRunAsManager());
interceptor.setAccessDecisionManager(new AccessDecisionManager() {
@@ -110,7 +110,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
interceptor.setObjectDefinitionSource(new FilterInvocationDefinitionMap());
interceptor.setObjectDefinitionSource(new RegExpBasedFilterInvocationDefinitionMap());
interceptor.setRunAsManager(new RunAsManager() {
public boolean supports(Class clazz) {
@@ -143,7 +143,7 @@ public class FilterSecurityInterceptorTests extends TestCase {
interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
interceptor.setAuthenticationManager(new MockAuthenticationManager());
FilterInvocationDefinitionMap fidp = new FilterInvocationDefinitionMap();
RegExpBasedFilterInvocationDefinitionMap fidp = new RegExpBasedFilterInvocationDefinitionMap();
interceptor.setObjectDefinitionSource(fidp);
interceptor.setRunAsManager(new MockRunAsManager());
interceptor.afterPropertiesSet();
@@ -0,0 +1,123 @@
/* Copyright 2004 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.intercept.web;
import junit.framework.TestCase;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.MockFilterChain;
import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.SecurityConfig;
/**
* Tests parts of {@link PathBasedFilterInvocationDefinitionMap} not tested by
* {@link FilterInvocationDefinitionSourceEditorWithPathsTests}.
*
* @author Ben Alex
* @version $Id$
*/
public class PathBasedFilterDefinitionMapTests extends TestCase {
//~ Constructors ===========================================================
public PathBasedFilterDefinitionMapTests() {
super();
}
public PathBasedFilterDefinitionMapTests(String arg0) {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(PathBasedFilterDefinitionMapTests.class);
}
public void testConvertUrlToLowercaseIsFalseByDefault() {
PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
}
public void testConvertUrlToLowercaseSetterRespected() {
PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap();
map.setConvertUrlToLowercaseBeforeComparison(true);
assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
}
public void testLookupNotRequiringExactMatchSuccessIfNotMatching() {
PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap();
map.setConvertUrlToLowercaseBeforeComparison(true);
assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
ConfigAttributeDefinition def = new ConfigAttributeDefinition();
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
map.addSecureUrl("/secure/super/**", def);
// Build a HTTP request
MockHttpServletRequest req = new MockHttpServletRequest(null);
req.setServletPath("/SeCuRE/super/somefile.html");
FilterInvocation fi = new FilterInvocation(req,
new MockHttpServletResponse(), new MockFilterChain());
ConfigAttributeDefinition response = map.lookupAttributes(fi);
assertEquals(def, response);
}
public void testLookupRequiringExactMatchFailsIfNotMatching() {
PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
ConfigAttributeDefinition def = new ConfigAttributeDefinition();
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
map.addSecureUrl("/secure/super/**", def);
// Build a HTTP request
MockHttpServletRequest req = new MockHttpServletRequest(null);
req.setServletPath("/SeCuRE/super/somefile.html");
FilterInvocation fi = new FilterInvocation(req,
new MockHttpServletResponse(), new MockFilterChain());
ConfigAttributeDefinition response = map.lookupAttributes(fi);
assertEquals(null, response);
}
public void testLookupRequiringExactMatchIsSuccessful() {
PathBasedFilterInvocationDefinitionMap map = new PathBasedFilterInvocationDefinitionMap();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
ConfigAttributeDefinition def = new ConfigAttributeDefinition();
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
map.addSecureUrl("/secure/super/**", def);
// Build a HTTP request
MockHttpServletRequest req = new MockHttpServletRequest(null);
req.setServletPath("/secure/super/somefile.html");
FilterInvocation fi = new FilterInvocation(req,
new MockHttpServletResponse(), new MockFilterChain());
ConfigAttributeDefinition response = map.lookupAttributes(fi);
assertEquals(def, response);
}
}
@@ -0,0 +1,123 @@
/* Copyright 2004 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.intercept.web;
import junit.framework.TestCase;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.MockFilterChain;
import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.SecurityConfig;
/**
* Tests parts of {@link RegExpBasedFilterInvocationDefinitionMap} not tested by {@link
* FilterInvocationDefinitionSourceEditorTests}.
*
* @author Ben Alex
* @version $Id$
*/
public class RegExpBasedFilterDefinitionMapTests extends TestCase {
//~ Constructors ===========================================================
public RegExpBasedFilterDefinitionMapTests() {
super();
}
public RegExpBasedFilterDefinitionMapTests(String arg0) {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(RegExpBasedFilterDefinitionMapTests.class);
}
public void testConvertUrlToLowercaseIsFalseByDefault() {
RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
}
public void testConvertUrlToLowercaseSetterRespected() {
RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap();
map.setConvertUrlToLowercaseBeforeComparison(true);
assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
}
public void testLookupNotRequiringExactMatchSuccessIfNotMatching() {
RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap();
map.setConvertUrlToLowercaseBeforeComparison(true);
assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
ConfigAttributeDefinition def = new ConfigAttributeDefinition();
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
map.addSecureUrl("\\A/secure/super.*\\Z", def);
// Build a HTTP request
MockHttpServletRequest req = new MockHttpServletRequest(null);
req.setServletPath("/SeCuRE/super/somefile.html");
FilterInvocation fi = new FilterInvocation(req,
new MockHttpServletResponse(), new MockFilterChain());
ConfigAttributeDefinition response = map.lookupAttributes(fi);
assertEquals(def, response);
}
public void testLookupRequiringExactMatchFailsIfNotMatching() {
RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
ConfigAttributeDefinition def = new ConfigAttributeDefinition();
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
map.addSecureUrl("\\A/secure/super.*\\Z", def);
// Build a HTTP request
MockHttpServletRequest req = new MockHttpServletRequest(null);
req.setServletPath("/SeCuRE/super/somefile.html");
FilterInvocation fi = new FilterInvocation(req,
new MockHttpServletResponse(), new MockFilterChain());
ConfigAttributeDefinition response = map.lookupAttributes(fi);
assertEquals(null, response);
}
public void testLookupRequiringExactMatchIsSuccessful() {
RegExpBasedFilterInvocationDefinitionMap map = new RegExpBasedFilterInvocationDefinitionMap();
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
ConfigAttributeDefinition def = new ConfigAttributeDefinition();
def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
map.addSecureUrl("\\A/secure/super.*\\Z", def);
// Build a HTTP request
MockHttpServletRequest req = new MockHttpServletRequest(null);
req.setServletPath("/secure/super/somefile.html");
FilterInvocation fi = new FilterInvocation(req,
new MockHttpServletResponse(), new MockFilterChain());
ConfigAttributeDefinition response = map.lookupAttributes(fi);
assertEquals(def, response);
}
}