浏览代码

Add RequestMatcher to AbstractPreAuthenticatedProcessingFilter

Moved the existing auth check logic to the matcher.

Issue: gh-5928
Tadaya Tsuyukubo 6 年之前
父节点
当前提交
62c7de03c3

+ 54 - 34
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 <code>Authentication</code> 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;
+		}
+
+	}
+
 }

+ 39 - 0
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();