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 f6b8fe113d..77e2a3a5ca 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 @@ -17,6 +17,7 @@ package org.springframework.security.ui.webapp; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; +import org.springframework.security.AuthenticationServiceException; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; @@ -54,6 +55,7 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY; private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY; + private boolean postOnly = true; //~ Constructors =================================================================================================== @@ -64,6 +66,10 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { //~ Methods ======================================================================================================== public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + if (postOnly && !request.getMethod().equals("POST")) { + throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); + } + String username = obtainUsername(request); String password = obtainPassword(request); @@ -151,6 +157,18 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { this.passwordParameter = passwordParameter; } + /** + * Defines whether only HTTP POST requests will be allowed by this filter. + * If set to true, and an authentication request is received which is not a POST request, an exception will + * be raised immediately and authentication will not be attempted. The unsuccessfulAuthentication() method + * will be called as if handling a failed authentication. + *
+ * Defaults to true but may be overridden by subclasses. + */ + public void setPostOnly(boolean postOnly) { + this.postOnly = postOnly; + } + public int getOrder() { return FilterChainOrder.AUTHENTICATION_PROCESSING_FILTER; } 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 2daef04992..9d3393bd63 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,6 +19,7 @@ import javax.servlet.ServletException; import junit.framework.TestCase; +import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.Authentication; @@ -36,17 +37,14 @@ import org.springframework.security.ui.WebAuthenticationDetails; public class AuthenticationProcessingFilterTests extends TestCase { //~ Methods ======================================================================================================== - public void testGetters() { - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); - assertEquals("/j_spring_security_check", filter.getFilterProcessesUrl()); - } - + @Test public void testNormalOperation() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod"); request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala"); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + assertEquals("/j_spring_security_check", filter.getFilterProcessesUrl()); filter.setAuthenticationManager(new MockAuthenticationManager(true)); filter.init(null); @@ -57,8 +55,9 @@ public class AuthenticationProcessingFilterTests extends TestCase { assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()); } + @Test public void testNullPasswordHandledGracefully() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod"); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); @@ -68,8 +67,9 @@ public class AuthenticationProcessingFilterTests extends TestCase { assertTrue(result != null); } + @Test public void testNullUsernameHandledGracefully() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala"); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); @@ -79,13 +79,14 @@ public class AuthenticationProcessingFilterTests extends TestCase { assertTrue(result != null); } + @Test public void testUsingDifferentParameterNamesWorksAsExpected() throws ServletException { AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager(true)); filter.setUsernameParameter("x"); filter.setPasswordParameter("y"); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); request.addParameter("x", "rod"); request.addParameter("y", "koala"); @@ -94,8 +95,9 @@ public class AuthenticationProcessingFilterTests extends TestCase { assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()); } + @Test public void testSpacesAreTrimmedCorrectlyFromUsername() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, " rod "); request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala"); @@ -106,8 +108,9 @@ public class AuthenticationProcessingFilterTests extends TestCase { assertEquals("rod", result.getName()); } + @Test public void testFailedAuthenticationThrowsException() { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/"); request.addParameter(AuthenticationProcessingFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod"); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); filter.setAuthenticationManager(new MockAuthenticationManager(false)); @@ -126,7 +129,8 @@ public class AuthenticationProcessingFilterTests extends TestCase { /** * SEC-571 */ - public void testNoSessionIsCreatedIfAllowSessionCreationIsFalse() throws Exception { + @Test + public void noSessionIsCreatedIfAllowSessionCreationIsFalse() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter();