diff --git a/core/src/main/java/org/springframework/security/ui/AbstractProcessingFilter.java b/core/src/main/java/org/springframework/security/ui/AbstractProcessingFilter.java index 001da04b8a..174a9eae1f 100644 --- a/core/src/main/java/org/springframework/security/ui/AbstractProcessingFilter.java +++ b/core/src/main/java/org/springframework/security/ui/AbstractProcessingFilter.java @@ -207,6 +207,8 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl */ private boolean migrateInvalidatedSessionAttributes = true; + private boolean allowSessionCreation = true; + //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { @@ -264,9 +266,15 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl } public static String obtainFullRequestUrl(HttpServletRequest request) { - SavedRequest savedRequest = (SavedRequest) request.getSession().getAttribute(SPRING_SECURITY_SAVED_REQUEST_KEY); + HttpSession session = request.getSession(false); - return (savedRequest == null) ? null : savedRequest.getFullRequestUrl(); + if (session == null) { + return null; + } + + SavedRequest savedRequest = (SavedRequest) session.getAttribute(SPRING_SECURITY_SAVED_REQUEST_KEY); + + return savedRequest == null ? null : savedRequest.getFullRequestUrl(); } protected void onPreAuthentication(HttpServletRequest request, HttpServletResponse response) @@ -434,8 +442,12 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl } try { - request.getSession().setAttribute(SPRING_SECURITY_LAST_EXCEPTION_KEY, failed); - } + HttpSession session = request.getSession(false); + + if (session != null || allowSessionCreation) { + request.getSession().setAttribute(SPRING_SECURITY_LAST_EXCEPTION_KEY, failed); + } + } catch (Exception ignored) { } @@ -558,4 +570,12 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl public void setUseRelativeContext(boolean useRelativeContext) { this.useRelativeContext = useRelativeContext; } + + protected boolean getAllowSessionCreation() { + return allowSessionCreation; + } + + public void setAllowSessionCreation(boolean allowSessionCreation) { + this.allowSessionCreation = allowSessionCreation; + } } diff --git a/core/src/main/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilter.java b/core/src/main/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilter.java index 63d5730efb..147a11c172 100644 --- a/core/src/main/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilter.java +++ b/core/src/main/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilter.java @@ -25,6 +25,7 @@ import org.springframework.security.ui.FilterChainOrderUtils; import org.springframework.util.Assert; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; /** @@ -72,7 +73,11 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Place the last username attempted into HttpSession for views - request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, username); + HttpSession session = request.getSession(false); + + if (session != null || getAllowSessionCreation()) { + request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, username); + } // Allow subclasses to set the "details" property setDetails(request, authRequest); diff --git a/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java b/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java index 64039a9c0a..8f34b2ed5d 100644 --- a/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java +++ b/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java @@ -471,11 +471,9 @@ public class AbstractProcessingFilterTests extends TestCase { MockHttpServletRequest request = createMockRequest(); HttpSession oldSession = request.getSession(); MockFilterConfig config = new MockFilterConfig(null, null); - MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); - // Setup our test object, to grant access MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); filter.setInvalidateSessionOnSuccessfulAuthentication(true); filter.setMigrateInvalidatedSessionAttributes(false); @@ -488,6 +486,27 @@ public class AbstractProcessingFilterTests extends TestCase { assertNull(newSession.getAttribute("test")); } + /** + * SEC-571 + */ + public void testNoSessionIsCreatedIfAllowSessionCreationIsFalse() throws Exception { + MockHttpServletRequest request = createMockRequest(); + + MockFilterConfig config = new MockFilterConfig(null, null); + MockFilterChain chain = new MockFilterChain(true); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Reject authentication, so exception would normally be stored in session + MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false); + filter.setAllowSessionCreation(false); + filter.setAuthenticationFailureUrl("/"); + filter.setDefaultTargetUrl("http://monkeymachine.co.uk/"); + + executeFilterInContainerSimulator(config, filter, request, response, chain); + + assertNull(request.getSession(false)); + } + //~ Inner Classes ================================================================================================== private class MockAbstractProcessingFilter extends AbstractProcessingFilter { diff --git a/core/src/test/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilterTests.java b/core/src/test/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilterTests.java index e1cce67dc3..625e9d1990 100644 --- a/core/src/test/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilterTests.java +++ b/core/src/test/java/org/springframework/security/ui/webapp/AuthenticationProcessingFilterTests.java @@ -19,10 +19,13 @@ import junit.framework.TestCase; import org.springframework.security.Authentication; import org.springframework.security.MockAuthenticationManager; +import org.springframework.security.AuthenticationException; import org.springframework.security.ui.WebAuthenticationDetails; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockFilterConfig; +import org.springframework.mock.web.MockHttpServletResponse; import javax.servlet.ServletException; @@ -61,6 +64,8 @@ public class AuthenticationProcessingFilterTests extends TestCase { Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); + assertEquals("rod", request.getSession().getAttribute( + AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY)); assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()); } @@ -70,7 +75,6 @@ public class AuthenticationProcessingFilterTests extends TestCase { AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager(true)); - filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); @@ -82,7 +86,6 @@ public class AuthenticationProcessingFilterTests extends TestCase { AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager(true)); - filter.init(null); Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); @@ -93,7 +96,6 @@ public class AuthenticationProcessingFilterTests extends TestCase { filter.setAuthenticationManager(new MockAuthenticationManager(true)); filter.setUsernameParameter("x"); filter.setPasswordParameter("y"); - filter.init(null); MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("x", "rod"); @@ -111,9 +113,40 @@ public class AuthenticationProcessingFilterTests extends TestCase { AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager(true)); - filter.init(null); Authentication result = filter.attemptAuthentication(request); assertEquals("rod", result.getName()); } + + public void testFailedAuthenticationThrowsException() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod"); + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + filter.setAuthenticationManager(new MockAuthenticationManager(false)); + + try { + filter.attemptAuthentication(request); + fail("Expected AuthenticationException"); + } catch (AuthenticationException e) { + } + + // Check username has still been set + assertEquals("rod", request.getSession().getAttribute( + AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY)); + } + + /** + * SEC-571 + */ + public void testNoSessionIsCreatedIfAllowSessionCreationIsFalse() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + filter.setAllowSessionCreation(false); + filter.setAuthenticationManager(new MockAuthenticationManager(true)); + + filter.attemptAuthentication(request); + + assertNull(request.getSession(false)); + } }