mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-08 19:42:48 +00:00
SEC-204: Improve startup time detection of errors by FilterInvocationDefinitionSourceEditor.
This commit is contained in:
parent
cc07f620df
commit
9b63051149
@ -1,4 +1,4 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
/* Copyright 2004, 2005, 2006 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.
|
||||
@ -28,8 +28,10 @@ import org.acegisecurity.ConfigAttributeDefinition;
|
||||
public interface FilterInvocationDefinitionMap {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void addSecureUrl(String expression, ConfigAttributeDefinition attr);
|
||||
|
||||
public boolean isConvertUrlToLowercaseBeforeComparison();
|
||||
|
||||
public void setConvertUrlToLowercaseBeforeComparison(
|
||||
boolean convertUrlToLowercaseBeforeComparison);
|
||||
|
||||
public void addSecureUrl(String expression, ConfigAttributeDefinition attr);
|
||||
}
|
||||
|
@ -55,6 +55,9 @@ public class FilterInvocationDefinitionSourceEditor
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FilterInvocationDefinitionSourceEditor.class);
|
||||
public static final String DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON =
|
||||
"CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON";
|
||||
public static final String DIRECTIVE_PATTERN_TYPE_APACHE_ANT = "PATTERN_TYPE_APACHE_ANT";
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
@ -65,14 +68,27 @@ public class FilterInvocationDefinitionSourceEditor
|
||||
// Leave target object empty
|
||||
} else {
|
||||
// Check if we need to override the default definition map
|
||||
if (s.lastIndexOf("PATTERN_TYPE_APACHE_ANT") != -1) {
|
||||
if (s.lastIndexOf(DIRECTIVE_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"));
|
||||
logger.debug(("Detected "
|
||||
+ DIRECTIVE_PATTERN_TYPE_APACHE_ANT
|
||||
+ " directive; using Apache Ant style path expressions"));
|
||||
}
|
||||
}
|
||||
|
||||
if (s.lastIndexOf(
|
||||
DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Detected "
|
||||
+ DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||
+ " directive; Instructing mapper to convert URLs to lowercase before comparison");
|
||||
}
|
||||
|
||||
source.setConvertUrlToLowercaseBeforeComparison(true);
|
||||
}
|
||||
|
||||
BufferedReader br = new BufferedReader(new StringReader(s));
|
||||
int counter = 0;
|
||||
String line;
|
||||
@ -100,17 +116,29 @@ public class FilterInvocationDefinitionSourceEditor
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.equals("CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON")) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Line " + counter
|
||||
+ ": Instructing mapper to convert URLs to lowercase before comparison");
|
||||
// Attempt to detect malformed lines (as per SEC-204)
|
||||
if (line.lastIndexOf(
|
||||
DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) {
|
||||
// Directive found; check for second directive or name=value
|
||||
if ((line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1)
|
||||
|| (line.lastIndexOf("=") != -1)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Line appears to be malformed: " + line);
|
||||
}
|
||||
}
|
||||
|
||||
source.setConvertUrlToLowercaseBeforeComparison(true);
|
||||
|
||||
continue;
|
||||
// Attempt to detect malformed lines (as per SEC-204)
|
||||
if (line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) {
|
||||
// Directive found; check for second directive or name=value
|
||||
if ((line.lastIndexOf(
|
||||
DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1)
|
||||
|| (line.lastIndexOf("=") != -1)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Line appears to be malformed: " + line);
|
||||
}
|
||||
}
|
||||
|
||||
// Skip lines that are not directives
|
||||
if (line.lastIndexOf('=') == -1) {
|
||||
continue;
|
||||
}
|
||||
@ -130,6 +158,24 @@ public class FilterInvocationDefinitionSourceEditor
|
||||
"Failed to parse a valid name/value pair from " + line);
|
||||
}
|
||||
|
||||
// Attempt to detect malformed lines (as per SEC-204)
|
||||
if (source.isConvertUrlToLowercaseBeforeComparison()
|
||||
&& source instanceof PathBasedFilterInvocationDefinitionMap) {
|
||||
// Should all be lowercase; check each character
|
||||
// We only do this for Ant (regexp have control chars)
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
String character = name.substring(i, i + 1);
|
||||
|
||||
if (!character.toLowerCase().equals(character)) {
|
||||
throw new IllegalArgumentException(
|
||||
"You are using the "
|
||||
+ DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||
+ " with Ant Paths, yet you have specified an uppercase character in line: "
|
||||
+ line + " (character '" + character + "')");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert value to series of security configuration attributes
|
||||
ConfigAttributeEditor configAttribEd = new ConfigAttributeEditor();
|
||||
configAttribEd.setAsText(value);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
/* Copyright 2004, 2005, 2006 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.
|
||||
@ -19,15 +19,13 @@ import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.ConfigAttributeDefinition;
|
||||
import org.acegisecurity.MockFilterChain;
|
||||
|
||||
|
||||
import org.acegisecurity.SecurityConfig;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link FilterInvocationDefinitionSourceEditor} and its associated
|
||||
@ -49,14 +47,14 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(FilterInvocationDefinitionSourceEditorTests.class);
|
||||
}
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testConvertUrlToLowercaseDefaultSettingUnchangedByEditor() {
|
||||
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
|
||||
editor.setAsText(
|
||||
@ -67,6 +65,19 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
|
||||
assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
|
||||
}
|
||||
|
||||
public void testConvertUrlToLowercaseDetectsUppercaseEntries() {
|
||||
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
|
||||
|
||||
try {
|
||||
editor.setAsText(
|
||||
"CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\nPATTERN_TYPE_APACHE_ANT\r\n\\/secUre/super/**=ROLE_WE_DONT_HAVE");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(expected.getMessage()
|
||||
.lastIndexOf("you have specified an uppercase character in line") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConvertUrlToLowercaseSettingApplied() {
|
||||
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
|
||||
editor.setAsText(
|
||||
@ -87,6 +98,45 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
|
||||
assertTrue(map instanceof RegExpBasedFilterInvocationDefinitionMap);
|
||||
}
|
||||
|
||||
public void testDetectsDuplicateDirectivesOnSameLineSituation1() {
|
||||
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
|
||||
|
||||
try {
|
||||
editor.setAsText(
|
||||
"CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT\r\n\\/secure/super/**=ROLE_WE_DONT_HAVE");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(expected.getMessage()
|
||||
.lastIndexOf("Line appears to be malformed") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsDuplicateDirectivesOnSameLineSituation2() {
|
||||
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
|
||||
|
||||
try {
|
||||
editor.setAsText(
|
||||
"CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\nPATTERN_TYPE_APACHE_ANT /secure/super/**=ROLE_WE_DONT_HAVE");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(expected.getMessage()
|
||||
.lastIndexOf("Line appears to be malformed") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDetectsDuplicateDirectivesOnSameLineSituation3() {
|
||||
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
|
||||
|
||||
try {
|
||||
editor.setAsText(
|
||||
"PATTERN_TYPE_APACHE_ANT\r\nCONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON /secure/super/**=ROLE_WE_DONT_HAVE");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(expected.getMessage()
|
||||
.lastIndexOf("Line appears to be malformed") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testEmptyStringReturnsEmptyMap() {
|
||||
FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
|
||||
editor.setAsText("");
|
||||
@ -158,7 +208,7 @@ public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
|
||||
Class clazz = RegExpBasedFilterInvocationDefinitionMap.EntryHolder.class;
|
||||
|
||||
try {
|
||||
clazz.getDeclaredConstructor((Class[])null);
|
||||
clazz.getDeclaredConstructor((Class[]) null);
|
||||
fail("Should have thrown NoSuchMethodException");
|
||||
} catch (NoSuchMethodException expected) {
|
||||
assertTrue(true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user