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 6e7a79ee8f..651300627f 100644 --- a/core/src/main/java/org/springframework/security/config/BeanIds.java +++ b/core/src/main/java/org/springframework/security/config/BeanIds.java @@ -46,6 +46,7 @@ public abstract class BeanIds { 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"; + public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter"; public static final String METHOD_SECURITY_INTERCEPTOR = "_methodSecurityInterceptor"; public static final String METHOD_DEFINITION_SOURCE_ADVISOR = "_methodDefinitionSourceAdvisor"; public static final String PROTECT_POINTCUT_POST_PROCESSOR = "_protectPointcutPostProcessor"; 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 260e2ee637..bfa42b5525 100644 --- a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java @@ -30,6 +30,7 @@ import org.springframework.security.securechannel.SecureChannelProcessor; import org.springframework.security.securechannel.RetryWithHttpEntryPoint; import org.springframework.security.securechannel.RetryWithHttpsEntryPoint; import org.springframework.security.ui.ExceptionTranslationFilter; +import org.springframework.security.ui.SessionFixationProtectionFilter; import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter; import org.springframework.security.util.FilterChainProxy; import org.springframework.security.util.RegexUrlPathMatcher; @@ -53,6 +54,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { static final String DEF_REALM = "Spring Security Application"; static final String ATT_PATH_PATTERN = "pattern"; + + static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection"; + static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none"; + static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession"; + static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession"; static final String ATT_PATH_TYPE = "path-type"; static final String DEF_PATH_TYPE_ANT = "ant"; @@ -109,6 +115,21 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE); httpScif.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); } + + String sessionFixationAttribute = element.getAttribute(ATT_SESSION_FIXATION_PROTECTION); + + if(!StringUtils.hasText(sessionFixationAttribute)) { + sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION; + } + + if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) { + BeanDefinitionBuilder sessionFixationFilter = + BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class); + sessionFixationFilter.addPropertyValue("migrateSessionAttributes", + sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)); + parserContext.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER, + sessionFixationFilter.getBeanDefinition()); + } BeanDefinitionBuilder filterSecurityInterceptorBuilder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class); @@ -127,6 +148,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { 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)); @@ -134,7 +156,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap); - // Set up the access manager and authentication mananger references for http + // Set up the access manager and authentication manager references for http String accessManagerId = element.getAttribute(ATT_ACCESS_MGR); if (!StringUtils.hasText(accessManagerId)) { diff --git a/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java b/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java index 5e994afff6..d17cc635bb 100644 --- a/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java +++ b/core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java @@ -6,6 +6,7 @@ import org.springframework.security.intercept.web.FilterInvocationDefinitionSour import org.springframework.security.intercept.web.FilterInvocation; import org.springframework.security.securechannel.ChannelProcessingFilter; import org.springframework.security.ui.ExceptionTranslationFilter; +import org.springframework.security.ui.SessionFixationProtectionFilter; import org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter; import org.springframework.security.ui.basicauth.BasicProcessingFilter; import org.springframework.security.ui.logout.LogoutFilter; @@ -56,7 +57,7 @@ public class HttpSecurityBeanDefinitionParserTests { @Test public void httpAutoConfigSetsUpCorrectFilterList() { - setContext("" + AUTH_PROVIDER_XML); + setContext("" + AUTH_PROVIDER_XML); FilterChainProxy filterChainProxy = getFilterChainProxy(); @@ -66,11 +67,12 @@ public class HttpSecurityBeanDefinitionParserTests { } private void checkAutoConfigFilters(List filterList) { - assertEquals("Expected 10 filters in chain", 10, filterList.size()); + assertEquals("Expected 11 filters in chain", 11, filterList.size()); Iterator filters = filterList.iterator(); assertTrue(filters.next() instanceof HttpSessionContextIntegrationFilter); + assertTrue(filters.next() instanceof SessionFixationProtectionFilter); assertTrue(filters.next() instanceof LogoutFilter); assertTrue(filters.next() instanceof AuthenticationProcessingFilter); assertTrue(filters.next() instanceof DefaultLoginPageGeneratingFilter); @@ -185,7 +187,7 @@ public class HttpSecurityBeanDefinitionParserTests { List filters = filterChainProxy.getFilters("/someurl"); - assertEquals("Expected 11 filters in chain", 11, filters.size()); + assertEquals("Expected 12 filters in chain", 12, filters.size()); assertTrue(filters.get(0) instanceof ChannelProcessingFilter); } @@ -216,7 +218,7 @@ public class HttpSecurityBeanDefinitionParserTests { ""); List filters = getFilterChainProxy().getFilters("/someurl"); - assertEquals(11, filters.size()); + assertEquals(12, filters.size()); assertTrue(filters.get(1) instanceof OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator); assertEquals("userFilter", ((OrderedFilterBeanDefinitionDecorator.OrderedFilterDecorator)filters.get(1)).getBeanName()); } @@ -242,9 +244,18 @@ public class HttpSecurityBeanDefinitionParserTests { "" + AUTH_PROVIDER_XML); List filters = getFilterChainProxy().getFilters("/someurl"); - assertTrue(filters.get(2) instanceof X509PreAuthenticatedProcessingFilter); + assertTrue(filters.get(3) instanceof X509PreAuthenticatedProcessingFilter); } + @Test + public void disablingSessionProtectionRemovesFilter() throws Exception { + setContext( + "" + AUTH_PROVIDER_XML); + List filters = getFilterChainProxy().getFilters("/someurl"); + + assertFalse(filters.get(1) instanceof SessionFixationProtectionFilter); + } + private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context); }