Browse Source

SEC-689: Session Fixation protection should be available to all authentication mechanisms.
http://jira.springframework.org/browse/SEC-689. Added support to namespace.

Luke Taylor 17 years ago
parent
commit
43b51ca64d

+ 1 - 0
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";

+ 23 - 1
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)) {

+ 16 - 5
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("<http auto-config='true'/>" + AUTH_PROVIDER_XML);
+        setContext("<http auto-config='true' />" + 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 {
                 "<b:bean id='userFilter2' class='org.springframework.security.util.MockFilter'/>");
         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 {
                 "</http>"  + 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(
+                "<http auto-config='true' session-fixation-protection='none'/>" + AUTH_PROVIDER_XML);
+        List filters = getFilterChainProxy().getFilters("/someurl");
+
+        assertFalse(filters.get(1) instanceof SessionFixationProtectionFilter);
+    }
+    
     private void setContext(String context) {
         appContext = new InMemoryXmlApplicationContext(context);
     }