diff --git a/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java b/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java index 862b3eaf00..ea8dd3c0ba 100755 --- a/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java +++ b/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java @@ -34,6 +34,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.WebAttributes; import org.springframework.security.web.authentication.*; +import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; import org.springframework.web.filter.GenericFilterBean; @@ -73,6 +74,7 @@ import org.springframework.web.filter.GenericFilterBean; * @author Luke Taylor * @author Ruud Senden * @author Rob Winch + * @author Tadaya Tsuyukubo * @since 2.0 */ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFilterBean @@ -86,6 +88,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi private boolean invalidateSessionOnPrincipalChange = true; private AuthenticationSuccessHandler authenticationSuccessHandler = null; private AuthenticationFailureHandler authenticationFailureHandler = null; + private RequestMatcher requiresAuthenticationRequestMatcher = new PreAuthenticatedProcessingRequestMatcher(); /** * Check whether all required properties have been set. @@ -114,7 +117,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi + SecurityContextHolder.getContext().getAuthentication()); } - if (requiresAuthentication((HttpServletRequest) request)) { + if (requiresAuthenticationRequestMatcher.matches((HttpServletRequest) request)) { doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response); } @@ -193,39 +196,6 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi } } - private boolean requiresAuthentication(HttpServletRequest request) { - Authentication currentUser = SecurityContextHolder.getContext() - .getAuthentication(); - - if (currentUser == null) { - return true; - } - - if (!checkForPrincipalChanges) { - return false; - } - - if (!principalChanged(request, currentUser)) { - return false; - } - - logger.debug("Pre-authenticated principal has changed and will be reauthenticated"); - - if (invalidateSessionOnPrincipalChange) { - SecurityContextHolder.clearContext(); - - HttpSession session = request.getSession(false); - - if (session != null) { - logger.debug("Invalidating existing session"); - session.invalidate(); - request.getSession(); - } - } - - return true; - } - /** * Puts the Authentication instance returned by the authentication * manager into the secure context. @@ -348,6 +318,14 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi this.authenticationFailureHandler = authenticationFailureHandler; } + /** + * Sets the request matcher to check whether to proceed the request further. + */ + public void setRequiresAuthenticationRequestMatcher(RequestMatcher requiresAuthenticationRequestMatcher) { + Assert.notNull(requiresAuthenticationRequestMatcher, "requestMatcher cannot be null"); + this.requiresAuthenticationRequestMatcher = requiresAuthenticationRequestMatcher; + } + /** * Override to extract the principal information from the current request */ @@ -359,4 +337,46 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi * return a dummy value. */ protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); + + /** + * Request matcher for default auth check logic + */ + private class PreAuthenticatedProcessingRequestMatcher implements RequestMatcher { + + @Override + public boolean matches(HttpServletRequest request) { + + Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); + + if (currentUser == null) { + return true; + } + + if (!checkForPrincipalChanges) { + return false; + } + + if (!principalChanged(request, currentUser)) { + return false; + } + + logger.debug("Pre-authenticated principal has changed and will be reauthenticated"); + + if (invalidateSessionOnPrincipalChange) { + SecurityContextHolder.clearContext(); + + HttpSession session = request.getSession(false); + + if (session != null) { + logger.debug("Invalidating existing session"); + session.invalidate(); + request.getSession(); + } + } + + return true; + } + + } + } diff --git a/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java index e741cef7b9..299f52df68 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java @@ -45,10 +45,12 @@ import org.springframework.security.core.userdetails.User; import org.springframework.security.web.WebAttributes; import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler; import org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; /** * * @author Rob Winch + * @author Tadaya Tsuyukubo * */ public class AbstractPreAuthenticatedProcessingFilterTests { @@ -376,6 +378,43 @@ public class AbstractPreAuthenticatedProcessingFilterTests { verifyZeroInteractions(am); } + @Test + public void requestNotMatchRequestMatcher() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + + ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter(); + filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/no-matching")); + + AuthenticationManager am = mock(AuthenticationManager.class); + filter.setAuthenticationManager(am); + filter.afterPropertiesSet(); + + filter.doFilter(request, response, chain); + + verifyZeroInteractions(am); + } + + @Test + public void requestMatchesRequestMatcher() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + + ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter(); + filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/**")); + + AuthenticationManager am = mock(AuthenticationManager.class); + filter.setAuthenticationManager(am); + filter.afterPropertiesSet(); + + filter.doFilter(request, response, chain); + + verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class)); + + } + private void testDoFilter(boolean grantAccess) throws Exception { MockHttpServletRequest req = new MockHttpServletRequest(); MockHttpServletResponse res = new MockHttpServletResponse();