SEC-1312: Add detection of 2.0 schemas. Added check to SecurityNamespaceHandler and reinstated old schemas.
This commit is contained in:
+103
-15
@@ -1,6 +1,14 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandler;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.config.authentication.AuthenticationManagerBeanDefinitionParser;
|
||||
import org.springframework.security.config.authentication.AuthenticationProviderBeanDefinitionParser;
|
||||
import org.springframework.security.config.authentication.JdbcUserServiceBeanDefinitionParser;
|
||||
@@ -14,6 +22,8 @@ import org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionPar
|
||||
import org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParser;
|
||||
import org.springframework.security.config.method.InterceptMethodsBeanDefinitionDecorator;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Registers the bean definition parsers for the "security" namespace (http://www.springframework.org/schema/security).
|
||||
@@ -23,28 +33,106 @@ import org.springframework.util.ClassUtils;
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
|
||||
public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
private final Map<String, BeanDefinitionParser> parsers = new HashMap<String, BeanDefinitionParser>();
|
||||
private final BeanDefinitionDecorator interceptMethodsBDD = new InterceptMethodsBeanDefinitionDecorator();
|
||||
private BeanDefinitionDecorator filterChainMapBDD;
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
if (!namespaceMatchesVersion(element)) {
|
||||
pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd schema with Spring Security 3.0." +
|
||||
" Please update your schema declarations to the 3.0 schema.", element);
|
||||
}
|
||||
String name = pc.getDelegate().getLocalName(element);
|
||||
BeanDefinitionParser parser = parsers.get(name);
|
||||
|
||||
if (parser == null) {
|
||||
if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name)) {
|
||||
reportMissingWebClasses(name, pc, element);
|
||||
} else {
|
||||
reportUnsupportedNodeType(name, pc, element);
|
||||
}
|
||||
}
|
||||
|
||||
return parser.parse(element, pc);
|
||||
}
|
||||
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext pc) {
|
||||
BeanDefinitionDecorator decorator = null;
|
||||
String name = pc.getDelegate().getLocalName(node);
|
||||
|
||||
// We only handle elements
|
||||
if (node instanceof Element) {
|
||||
if (Elements.INTERCEPT_METHODS.equals(name)) {
|
||||
return interceptMethodsBDD.decorate(node, definition, pc);
|
||||
}
|
||||
|
||||
if (Elements.FILTER_CHAIN_MAP.equals(name)) {
|
||||
if (filterChainMapBDD == null) {
|
||||
reportMissingWebClasses(name, pc, node);
|
||||
}
|
||||
return filterChainMapBDD.decorate(node, definition, pc);
|
||||
}
|
||||
}
|
||||
|
||||
if (decorator == null) {
|
||||
reportUnsupportedNodeType(name, pc, node);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void reportUnsupportedNodeType(String name, ParserContext pc, Node node) {
|
||||
pc.getReaderContext().fatal("Security namespace does not support decoration of " +
|
||||
(node instanceof Element ? "element" : "attribute") + " [" + name + "]", node);
|
||||
}
|
||||
|
||||
private void reportMissingWebClasses(String nodeName, ParserContext pc, Node node) {
|
||||
pc.getReaderContext().fatal("spring-security-web classes are not available. " +
|
||||
"You need these to use <" + Elements.FILTER_CHAIN_MAP + ">", node);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void init() {
|
||||
// Parsers
|
||||
registerBeanDefinitionParser(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.LDAP_USER_SERVICE, new LdapUserServiceBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.USER_SERVICE, new UserServiceBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.JDBC_USER_SERVICE, new JdbcUserServiceBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
|
||||
registerBeanDefinitionDecorator(Elements.INTERCEPT_METHODS, new InterceptMethodsBeanDefinitionDecorator());
|
||||
parsers.put(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser());
|
||||
parsers.put(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser());
|
||||
parsers.put(Elements.LDAP_USER_SERVICE, new LdapUserServiceBeanDefinitionParser());
|
||||
parsers.put(Elements.USER_SERVICE, new UserServiceBeanDefinitionParser());
|
||||
parsers.put(Elements.JDBC_USER_SERVICE, new JdbcUserServiceBeanDefinitionParser());
|
||||
parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
|
||||
parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
|
||||
parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
|
||||
// registerBeanDefinitionDecorator(Elements.INTERCEPT_METHODS, new InterceptMethodsBeanDefinitionDecorator());
|
||||
|
||||
// Web-namespace stuff
|
||||
if (ClassUtils.isPresent("org.springframework.security.web.FilterChainProxy", ClassUtils.getDefaultClassLoader())) {
|
||||
registerBeanDefinitionParser(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
|
||||
registerBeanDefinitionDecorator(Elements.FILTER_CHAIN_MAP, new FilterChainMapBeanDefinitionDecorator());
|
||||
registerBeanDefinitionParser(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||
registerBeanDefinitionParser(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||
parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
|
||||
parsers.put(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
|
||||
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
||||
//registerBeanDefinitionDecorator(Elements.FILTER_CHAIN_MAP, new FilterChainMapBeanDefinitionDecorator());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the schema location declared in the source file being parsed matches the Spring Batch version.
|
||||
* The old 2.0 schema is not compatible with the new 3.0 parser, so it is an error to explicitly use
|
||||
* 3.0. It might be an error to declare spring-security.xsd as an alias, but you are only going to find that out
|
||||
* when one of the sub parsers breaks.
|
||||
*
|
||||
* @param element the element that is to be parsed next
|
||||
* @return true if we find a schema declaration that matches
|
||||
*/
|
||||
private boolean namespaceMatchesVersion(Element element) {
|
||||
return matchesVersionInternal(element) && matchesVersionInternal(element.getOwnerDocument().getDocumentElement());
|
||||
}
|
||||
|
||||
private boolean matchesVersionInternal(Element element) {
|
||||
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
||||
return schemaLocation.matches("(?m).*spring-security-3.0.xsd.*")
|
||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-3.0.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-3.0.xsd=org/springframework/security/config/spring-security-3.0.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
|
||||
|
||||
+1335
File diff suppressed because it is too large
Load Diff
+1422
File diff suppressed because it is too large
Load Diff
+1468
File diff suppressed because it is too large
Load Diff
+1251
File diff suppressed because it is too large
Load Diff
+30
@@ -0,0 +1,30 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SecurityNamespacehandlerTests {
|
||||
|
||||
@Test
|
||||
public void pre3SchemaAreNotSupported() throws Exception {
|
||||
try {
|
||||
new InMemoryXmlApplicationContext(
|
||||
"<user-service id='us'>" +
|
||||
" <user name='bob' password='bobspassword' authorities='ROLE_A' />" +
|
||||
"</user-service>", "2.0.4", null
|
||||
);
|
||||
fail("Expected BeanDefinitionParsingException");
|
||||
} catch (BeanDefinitionParsingException expected) {
|
||||
assertTrue(expected.getMessage().contains("You cannot use a spring-security-2.0.xsd schema"));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user