Made servlet-api integration into an attribute of http, rather than a child element since it has no configuration.

This commit is contained in:
Luke Taylor 2007-12-20 17:51:27 +00:00
parent 1c9bd8bf5f
commit 85b10f79c2
6 changed files with 81 additions and 93 deletions

View File

@ -2,7 +2,7 @@ package org.springframework.security.config;
/**
* Contains all the element names used by Spring Security 2 namespace support.
*
*
* @author Ben Alex
* @version $Id$
*/
@ -25,7 +25,6 @@ class Elements {
public static final String REMEMBER_ME = "remember-me";
public static final String ANONYMOUS = "anonymous";
public static final String FILTER_CHAIN = "filter-chain";
public static final String SERVLET_API_INTEGRATION = "servlet-api-integration";
public static final String ANNOTATION_DRIVEN = "annotation-driven";
}

View File

@ -16,6 +16,7 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.ConfigAttributeEditor;
import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.intercept.web.AbstractFilterInvocationDefinitionSource;
import org.springframework.security.intercept.web.FilterInvocationDefinitionMap;
@ -47,7 +48,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
static final String DEF_REALM = "Spring Security Application";
static final String ATT_PATH_PATTERN = "pattern";
static final String ATT_PATH_TYPE = "path-type";
static final String DEF_PATH_TYPE_ANT = "ant";
static final String OPT_PATH_TYPE_REGEX = "regex";
@ -62,13 +63,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
static final String DEF_CREATE_SESSION_IF_REQUIRED = "ifRequired";
static final String OPT_CREATE_SESSION_ALWAYS = "always";
static final String OPT_CREATE_SESSION_NEVER = "never";
static final String ATT_LOWERCASE_COMPARISONS = "lowercase-comparisons";
static final String DEF_LOWERCASE_COMPARISONS = "true";
static final String ATT_AUTO_CONFIG = "auto-config";
static final String DEF_AUTO_CONFIG = "false";
static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
static final String DEF_SERVLET_API_PROVISION = "true";
public BeanDefinition parse(Element element, ParserContext parserContext) {
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
@ -85,7 +89,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
}
BeanDefinitionBuilder filterSecurityInterceptorBuilder
= BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
@ -120,7 +124,17 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
interceptorFilterInvDefSource.setConvertUrlToLowercaseBeforeComparison(false);
channelFilterInvDefSource.setConvertUrlToLowercaseBeforeComparison(false);
}
// Add servlet-api integration filter if required
String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
if (!StringUtils.hasText(provideServletApi)) {
provideServletApi = DEF_SERVLET_API_PROVISION;
}
if ("true".equals(provideServletApi)) {
parserContext.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER,
new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class));
}
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
@ -148,7 +162,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
registry.registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
registry.registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
}
String realm = element.getAttribute(ATT_REALM);
if (!StringUtils.hasText(realm)) {
realm = DEF_REALM;
@ -158,17 +172,17 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
if (sessionControlElt != null) {
new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
}
boolean autoConfig = false;
if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
autoConfig = true;
}
Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
if (anonymousElt != null || autoConfig) {
new AnonymousBeanDefinitionParser().parse(anonymousElt, parserContext);
}
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(element, Elements.REMEMBER_ME);
if (rememberMeElt != null || autoConfig) {
@ -184,17 +198,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
if (formLoginElt != null || autoConfig) {
new FormLoginBeanDefinitionParser().parse(formLoginElt, parserContext);
}
Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
if (basicAuthElt != null || autoConfig) {
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, parserContext);
}
Element servletApiIntegrationElt = DomUtils.getChildElementByTagName(element, Elements.SERVLET_API_INTEGRATION);
if (servletApiIntegrationElt != null || autoConfig) {
new ServletApiIntegrationBeanDefinitionParser().parse(servletApiIntegrationElt, parserContext);
}
registry.registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
registry.registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
registry.registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());

View File

@ -1,25 +0,0 @@
package org.springframework.security.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter;
import org.w3c.dom.Element;
/**
* @author Ben Alex
* @version $Id$
*/
public class ServletApiIntegrationBeanDefinitionParser implements BeanDefinitionParser {
protected final Log logger = LogFactory.getLog(getClass());
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinition filter = new RootBeanDefinition(SecurityContextHolderAwareRequestFilter.class);
parserContext.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER, filter);
System.out.println("********************");
return null;
}
}

View File

@ -8,8 +8,6 @@ default namespace = "http://www.springframework.org/schema/security"
start = http | ldap | repository
# targetNamespace="http://www.springframework.org/schema/security"
hash =
## Defines the type of hashing used on user passwords. If unspecified, "plaintext" is nominated, which indicates that the passwords are not hashed. We recommend strongly against using MD4, as it is a very weak hashing algorithm.
attribute hash {"plaintext" | "sha-hex" | "sha-base64" | "md5-hex" | "md5-base64" | "md4-hex" | "md4-base64"}
@ -17,39 +15,39 @@ hash =
path-type =
## Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.
attribute path-type {"ant" | "regex"}
port =
## Specifies an IP port number. Used to configure an embedded LDAP server, for example.
attribute port { xsd:integer }
## Specifies an IP port number. Used to configure an embedded LDAP server, for example.
attribute port { xsd:integer }
url =
## Specifies a URL.
attribute url { xsd:string }
ldap =
ldap =
## Sets up an ldap authentication provider, optionally with an embedded ldap server
element ldap {ldap.attlist, empty}
ldap.attlist &=
## The url indicates the server location. If omitted, an embedded server will be started, optionally with the configured port number.
(url | port)?
ldap.attlist &=
## Explicitly specify an ldif file resource to load into the embedded server
[ a:defaultValue = "classpath:*.ldif" ] attribute ldif { xsd:string }?
intercept-methods =
intercept-methods =
## Can be used inside a bean definition to add a security interceptor to the bean and set up access configuration attributes for the bean's methods
element intercept-methods {intercept-methods.attlist, protect+}
element intercept-methods {intercept-methods.attlist, protect+}
intercept-methods.attlist = empty
protect =
protect =
## Defines a protected method and the access control configuration attributes that apply to it
element protect {protect.attlist, empty}
protect.attlist &=
## A method name
## A method name
attribute method {xsd:string}
protect.attlist &=
## Access configuration attributes list that applies to the method, e.g. "ROLE_A,ROLE_B"
@ -58,14 +56,14 @@ protect.attlist &=
annotation-driven =
## Activates security annotation scanning. All beans registered in the Spring application context will be scanned for Spring Security annotations. Where found, the beans will automatically be proxied and security authorization applied to the methods accordingly. Please ensure you have the spring-security-tiger-XXX.jar on your classpath.
element annotation-driven {annotation-driven.attlist}
element annotation-driven {annotation-driven.attlist}
annotation-driven.attlist = empty
http =
## Container element for HTTP security configuration
element http {http.attlist, (intercept-url+ & form-login? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous? & servlet-api-integration?) }
element http {http.attlist, (intercept-url+ & form-login? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous?) }
http.attlist &=
## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".
attribute auto-config {"true" | "false" }?
@ -73,11 +71,14 @@ http.attlist &=
## Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired".
attribute create-session {"ifRequired" | "always" | "never" }?
http.attlist &=
## The path format used to define the paths in child elements.
## The path format used to define the paths in child elements.
path-type?
http.attlist &=
## Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true".
attribute lowercase-comparisons {"true" | "false"}?
http.attlist &=
## Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".
attribute servlet-api-provision {"true" | "false"}?
http.attlist &=
## Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.
attribute access-decision-manager {xsd:string}?
@ -90,8 +91,8 @@ intercept-url =
## Specifies the access attributes and/or filter list for a particular set of URLs.
element intercept-url {intercept-url.attlist, empty}
intercept-url.attlist &=
## The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.
attribute pattern {xsd:string}
## The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.
attribute pattern {xsd:string}
intercept-url.attlist &=
## The access configuration attributes that apply for the configured path.
attribute access {xsd:string}?
@ -117,32 +118,32 @@ logout.attlist &=
form-login =
## Sets up a form login configuration
element form-login {form-login.attlist, empty}
element form-login {form-login.attlist, empty}
form-login.attlist &=
## The URL that the login form is posted to. If unspecified, it defaults to /j_spring_security_check.
attribute login-url {xsd:string}?
attribute login-url {xsd:string}?
form-login.attlist &=
## The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed. This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication. If unspecified, defaults to the root of the application.
attribute default-target-url {xsd:string}?
attribute default-target-url {xsd:string}?
form-login.attlist &=
## The URL for the login page. If no login URL is specified, Spring Security will automatically create a login URL at /spring_security_login and a corresponding filter to render that login URL when requested.
attribute login-page {xsd:string}?
attribute login-page {xsd:string}?
form-login.attlist &=
## The URL for the login failure page. If no login failure URL is specified, Spring Security will automatically create a failure login URL at /spring_security_login?login_error and a corresponding filter to render that login failure URL when requested.
attribute authentication-failure-url {xsd:string}?
attribute authentication-failure-url {xsd:string}?
filter-chain-map =
filter-chain-map =
## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
element filter-chain-map {filter-chain-map.attlist, filter-chain+}
filter-chain-map.attlist &=
path-type
path-type
filter-chain =
## Used within filter-chain-map to define a specific URL pattern and the list of filters which apply to the URLs matching that pattern. When multiple filter-chain elements are used within a filter-chain-map element, the most specific patterns must be placed at the top of the list, with most general ones at the bottom.
element filter-chain {filter-chain.attlist, empty}
filter-chain.attlist &=
filter-chain.attlist &=
attribute pattern {xsd:string}
filter-chain.attlist &=
filter-chain.attlist &=
attribute filters {xsd:string}
http-basic =
@ -160,23 +161,19 @@ concurrent-sessions.attlist &=
concurrent-sessions.attlist &=
attribute exception-if-maximum-exceeded {"true" | "false"}?
remember-me =
element remember-me {remember-me.attlist}
remember-me.attlist &=
(attribute key {xsd:string} | (attribute token-repository {xsd:string} | attribute data-source {xsd:string}))
servlet-api-integration =
element servlet-api-integration {servlet-api-integration.attlist}
servlet-api-integration.attlist = empty
remember-me =
element remember-me {remember-me.attlist}
remember-me.attlist &=
(attribute key {xsd:string} | (attribute token-repository {xsd:string} | attribute data-source {xsd:string}))
anonymous =
anonymous =
## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.
element anonymous {anonymous.attlist}
element anonymous {anonymous.attlist}
anonymous.attlist &=
## The key used between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".
attribute key {xsd:string}?
anonymous.attlist &=
## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
attribute username {xsd:string}?
anonymous.attlist &=
## The granted authority that should be assigned to the anonymous request. Commonly this is used to assign the anonymous request particular roles, which can subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".
@ -205,7 +202,7 @@ user.attlist &=
## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element).
attribute password {xsd:string}
user.attlist &=
## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"
attribute authorities {xsd:string}
jdbc-user-service =

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.springframework.org/schema/security" xmlns:security="http://www.springframework.org/schema/security">
<!-- targetNamespace="http://www.springframework.org/schema/security" -->
<xs:attributeGroup name="hash">
<xs:attribute name="hash" use="required">
<xs:annotation>
@ -35,7 +34,7 @@
<xs:attributeGroup name="port">
<xs:attribute name="port" use="required" type="xs:integer">
<xs:annotation>
<xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example. </xs:documentation>
<xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
@ -62,7 +61,7 @@
</xs:attribute>
<xs:attribute name="port" type="xs:integer">
<xs:annotation>
<xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example. </xs:documentation>
<xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server, for example.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ldif" default="classpath:*.ldif" type="xs:string">
@ -92,7 +91,7 @@
<xs:attributeGroup name="protect.attlist">
<xs:attribute name="method" use="required" type="xs:string">
<xs:annotation>
<xs:documentation>A method name </xs:documentation>
<xs:documentation>A method name</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="access" use="required" type="xs:string">
@ -120,7 +119,6 @@
<xs:element ref="security:concurrent-session-control"/>
<xs:element ref="security:remember-me"/>
<xs:element ref="security:anonymous"/>
<xs:element ref="security:servlet-api-integration"/>
</xs:choice>
<xs:attributeGroup ref="security:http.attlist"/>
</xs:complexType>
@ -171,6 +169,17 @@
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="servlet-api-provision">
<xs:annotation>
<xs:documentation>Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="access-decision-manager" type="xs:string">
<xs:annotation>
<xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.</xs:documentation>
@ -193,7 +202,7 @@
<xs:attributeGroup name="intercept-url.attlist">
<xs:attribute name="pattern" use="required" type="xs:string">
<xs:annotation>
<xs:documentation>The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax. </xs:documentation>
<xs:documentation>The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="access" type="xs:string">
@ -346,9 +355,6 @@
<xs:attribute name="token-repository" type="xs:string"/>
<xs:attribute name="data-source" type="xs:string"/>
</xs:attributeGroup>
<xs:element name="servlet-api-integration">
<xs:complexType/>
</xs:element>
<xs:element name="anonymous">
<xs:annotation>
<xs:documentation>Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.</xs:documentation>
@ -365,7 +371,7 @@
</xs:attribute>
<xs:attribute name="username" type="xs:string">
<xs:annotation>
<xs:documentation>The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser". </xs:documentation>
<xs:documentation>The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="granted-authority" type="xs:string">
@ -445,7 +451,7 @@
</xs:attribute>
<xs:attribute name="authorities" use="required" type="xs:string">
<xs:annotation>
<xs:documentation>One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" </xs:documentation>
<xs:documentation>One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>

View File

@ -11,6 +11,7 @@ import org.springframework.security.ui.rememberme.RememberMeProcessingFilter;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter;
import org.springframework.security.util.FilterChainProxy;
import org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.junit.AfterClass;
@ -58,7 +59,7 @@ public class HttpSecurityBeanDefinitionParserTests {
List filterList = filterChainProxy.getFilters("/someurl");
assertEquals("Expected 10 filters in chain", 10, filterList.size());
assertEquals("Expected 11 filters in chain", 11, filterList.size());
Iterator filters = filterList.iterator();
@ -69,6 +70,7 @@ public class HttpSecurityBeanDefinitionParserTests {
assertTrue(filters.next() instanceof AuthenticationProcessingFilter);
assertTrue(filters.next() instanceof DefaultLoginPageGeneratingFilter);
assertTrue(filters.next() instanceof BasicProcessingFilter);
assertTrue(filters.next() instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.next() instanceof RememberMeProcessingFilter);
assertTrue(filters.next() instanceof ExceptionTranslationFilter);
assertTrue(filters.next() instanceof FilterSecurityInterceptor);