diff --git a/core/src/main/java/org/springframework/security/config/BeanIds.java b/core/src/main/java/org/springframework/security/config/BeanIds.java index b464b8bb14..fd3567f31f 100644 --- a/core/src/main/java/org/springframework/security/config/BeanIds.java +++ b/core/src/main/java/org/springframework/security/config/BeanIds.java @@ -34,7 +34,6 @@ public class BeanIds { public static final String REMEMBER_ME_FILTER = "_rememberMeFilter"; public static final String REMEMBER_ME_SERVICES = "_rememberMeServices"; public static final String DEFAULT_LOGIN_PAGE_GENERATING_FILTER = "_defaultLoginPageFilter"; - - + public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter"; } diff --git a/core/src/main/java/org/springframework/security/config/Elements.java b/core/src/main/java/org/springframework/security/config/Elements.java index a1a7e77773..a12af355e7 100644 --- a/core/src/main/java/org/springframework/security/config/Elements.java +++ b/core/src/main/java/org/springframework/security/config/Elements.java @@ -25,5 +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"; } diff --git a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java index e27d89e797..38ef62fe81 100644 --- a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java @@ -190,12 +190,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { 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()); registry.registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, filterSecurityInterceptorBuilder.getBeanDefinition()); - // Register the post processor which will tie up the loose ends in the configuration once the app context has been created and all beans are available. registry.registerBeanDefinition("__httpConfigBeanFactoryPostProcessor", new RootBeanDefinition(HttpSecurityConfigPostProcessor.class)); diff --git a/core/src/main/java/org/springframework/security/config/ServletApiIntegrationBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/ServletApiIntegrationBeanDefinitionParser.java new file mode 100644 index 0000000000..f6f5b5c890 --- /dev/null +++ b/core/src/main/java/org/springframework/security/config/ServletApiIntegrationBeanDefinitionParser.java @@ -0,0 +1,25 @@ +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; + } +} diff --git a/core/src/main/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilter.java b/core/src/main/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilter.java index fe56ddfee6..e83445650f 100644 --- a/core/src/main/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilter.java +++ b/core/src/main/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilter.java @@ -15,23 +15,20 @@ package org.springframework.security.wrapper; -import org.springframework.security.util.PortResolver; -import org.springframework.security.util.PortResolverImpl; - -import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; - import java.io.IOException; - import java.lang.reflect.Constructor; -import javax.servlet.Filter; import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.ui.FilterChainOrderUtils; +import org.springframework.security.ui.SpringSecurityFilter; +import org.springframework.security.util.PortResolver; +import org.springframework.security.util.PortResolverImpl; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; /** @@ -47,7 +44,7 @@ import javax.servlet.http.HttpServletRequest; * @author Ben Alex * @version $Id$ */ -public class SecurityContextHolderAwareRequestFilter implements Filter { +public class SecurityContextHolderAwareRequestFilter extends SpringSecurityFilter { //~ Instance fields ================================================================================================ private Class wrapperClass = SavedRequestAwareWrapper.class; @@ -57,12 +54,23 @@ public class SecurityContextHolderAwareRequestFilter implements Filter { //~ Methods ======================================================================================================== - public void destroy() {} + public void setPortResolver(PortResolver portResolver) { + Assert.notNull(portResolver, "PortResolver required"); + this.portResolver = portResolver; + } - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; + public void setWrapperClass(Class wrapperClass) { + Assert.notNull(wrapperClass, "WrapperClass required"); + Assert.isTrue(HttpServletRequest.class.isAssignableFrom(wrapperClass), "Wrapper must be a HttpServletRequest"); + this.wrapperClass = wrapperClass; + } + public void setRolePrefix(String rolePrefix) { + Assert.notNull(rolePrefix, "Role prefix must not be null"); + this.rolePrefix = rolePrefix.trim(); + } + + protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (!wrapperClass.isAssignableFrom(request.getClass())) { if (constructor == null) { try { @@ -80,24 +88,10 @@ public class SecurityContextHolderAwareRequestFilter implements Filter { } } - filterChain.doFilter(request, servletResponse); - } + chain.doFilter(request, response); + } - public void init(FilterConfig filterConfig) throws ServletException {} - - public void setPortResolver(PortResolver portResolver) { - Assert.notNull(portResolver, "PortResolver required"); - this.portResolver = portResolver; - } - - public void setWrapperClass(Class wrapperClass) { - Assert.notNull(wrapperClass, "WrapperClass required"); - Assert.isTrue(HttpServletRequest.class.isAssignableFrom(wrapperClass), "Wrapper must be a HttpServletRequest"); - this.wrapperClass = wrapperClass; - } - - public void setRolePrefix(String rolePrefix) { - Assert.notNull(rolePrefix, "Role prefix must not be null"); - this.rolePrefix = rolePrefix.trim(); - } + public int getOrder() { + return FilterChainOrderUtils.SECURITY_CONTEXT_HOLDER_AWARE_FILTER_ORDER; + } } diff --git a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc index e57a361163..5e83a7e254 100644 --- a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc +++ b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc @@ -57,9 +57,9 @@ protect.attlist &= http = ## Container element for HTTP security configuration - element http {http.attlist, (intercept-url+ & form-login? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous?) } + element http {http.attlist, (intercept-url+ & form-login? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous? & servlet-api-integration?) } http.attlist &= - ## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services and remember-me. 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". + ## 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 autoConfig {"true" | "false" }? http.attlist &= ## Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired". @@ -157,6 +157,10 @@ remember-me = remember-me.attlist &= (attribute key {xsd:string} | (attribute tokenRepository {xsd:string} | attribute datasource {xsd:string})) +servlet-api-integration = + element servlet-api-integration {servlet-api-integration.attlist} +servlet-api-integration.attlist = empty + anonymous = ## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. element anonymous {anonymous.attlist} diff --git a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd index f3ea903694..fe1cfc808f 100644 --- a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd +++ b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd @@ -114,6 +114,7 @@ + @@ -121,7 +122,7 @@ - Automatically registers a login form, BASIC authentication, anonymous authentication, logout services and remember-me. 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". + 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". @@ -339,6 +340,9 @@ + + + Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority. diff --git a/core/src/test/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilterTests.java b/core/src/test/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilterTests.java index 9bd8227913..27cb2852b5 100644 --- a/core/src/test/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilterTests.java +++ b/core/src/test/java/org/springframework/security/wrapper/SecurityContextHolderAwareRequestFilterTests.java @@ -20,6 +20,7 @@ import junit.framework.TestCase; import org.springframework.security.MockFilterConfig; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; @@ -54,11 +55,11 @@ public class SecurityContextHolderAwareRequestFilterTests extends TestCase { public void testCorrectOperation() throws Exception { SecurityContextHolderAwareRequestFilter filter = new SecurityContextHolderAwareRequestFilter(); filter.init(new MockFilterConfig()); - filter.doFilter(new MockHttpServletRequest(null, null), null, + filter.doFilter(new MockHttpServletRequest(null, null), new MockHttpServletResponse(), new MockFilterChain(SavedRequestAwareWrapper.class)); // Now re-execute the filter, ensuring our replacement wrapper is still used - filter.doFilter(new MockHttpServletRequest(null, null), null, + filter.doFilter(new MockHttpServletRequest(null, null), new MockHttpServletResponse(), new MockFilterChain(SavedRequestAwareWrapper.class)); filter.destroy(); diff --git a/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml b/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml index 97527507c8..21c063e4c4 100644 --- a/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml +++ b/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml @@ -23,8 +23,9 @@ + --> - + diff --git a/samples/tutorial/src/main/webapp/index.jsp b/samples/tutorial/src/main/webapp/index.jsp index b8c5668259..318c284d0e 100644 --- a/samples/tutorial/src/main/webapp/index.jsp +++ b/samples/tutorial/src/main/webapp/index.jsp @@ -1,7 +1,9 @@

Home Page

-Anyone can view this page. +Anyone can view this page.

+ +Your principal object is....: <%= request.getUserPrincipal() %>

Secure page

Extremely secure page diff --git a/samples/tutorial/src/main/webapp/secure/index.jsp b/samples/tutorial/src/main/webapp/secure/index.jsp index 2c2608a720..b774c40ed8 100644 --- a/samples/tutorial/src/main/webapp/secure/index.jsp +++ b/samples/tutorial/src/main/webapp/secure/index.jsp @@ -2,7 +2,12 @@

Secure Page

This is a protected page. You can get to me if you've been remembered, -or if you've authenticated this session. +or if you've authenticated this session.

+ +<%if (request.isUserInRole("ROLE_SUPERVISOR")) { %> + You are a supervisor! You can therefore see the extremely secure page.

+<% } %> +

Home

Logout