Explorar o código

Add constructors to AbstractAuthenticationProcessingFilter

Closes gh-8309
Oh Myung Woon %!s(int64=5) %!d(string=hai) anos
pai
achega
b7d3acc02c

+ 27 - 0
web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java

@@ -156,6 +156,33 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
 		this.requiresAuthenticationRequestMatcher = requiresAuthenticationRequestMatcher;
 	}
 
+	/**
+	 * Creates a new instance with a default filterProcessesUrl and an {@link AuthenticationManager}
+	 *
+	 * @param defaultFilterProcessesUrl the default value for <tt>filterProcessesUrl</tt>.
+	 * @param authenticationManager the {@link AuthenticationManager} used to authenticate an {@link Authentication} object.
+	 *                              Cannot be null.
+	 */
+	protected AbstractAuthenticationProcessingFilter(String defaultFilterProcessesUrl,
+			AuthenticationManager authenticationManager) {
+		setFilterProcessesUrl(defaultFilterProcessesUrl);
+		setAuthenticationManager(authenticationManager);
+	}
+
+	/**
+	 * Creates a new instance with a {@link RequestMatcher} and an {@link AuthenticationManager}
+	 *
+	 * @param requiresAuthenticationRequestMatcher the {@link RequestMatcher} used to determine
+	 *                                             if authentication is required. Cannot be null.
+	 * @param authenticationManager the {@link AuthenticationManager} used to authenticate an {@link Authentication} object.
+	 *                              Cannot be null.
+	 */
+	protected AbstractAuthenticationProcessingFilter(RequestMatcher requiresAuthenticationRequestMatcher,
+			AuthenticationManager authenticationManager) {
+		setRequiresAuthenticationRequestMatcher(requiresAuthenticationRequestMatcher);
+		setAuthenticationManager(authenticationManager);
+	}
+
 	// ~ Methods
 	// ========================================================================================================
 

+ 8 - 1
web/src/main/java/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java

@@ -17,6 +17,7 @@
 package org.springframework.security.web.authentication;
 
 import org.springframework.lang.Nullable;
+import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
@@ -51,6 +52,8 @@ public class UsernamePasswordAuthenticationFilter extends
 
 	public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
 	public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
+	private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER =
+			new AntPathRequestMatcher("/login", "POST");
 
 	private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
 	private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
@@ -60,7 +63,11 @@ public class UsernamePasswordAuthenticationFilter extends
 	// ===================================================================================================
 
 	public UsernamePasswordAuthenticationFilter() {
-		super(new AntPathRequestMatcher("/login", "POST"));
+		super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
+	}
+
+	public UsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
+		super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
 	}
 
 	// ~ Methods

+ 98 - 4
web/src/test/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilterTests.java

@@ -50,6 +50,8 @@ import org.springframework.security.web.authentication.rememberme.AbstractRememb
 import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
 import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
 import org.springframework.security.web.firewall.DefaultHttpFirewall;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.test.util.ReflectionTestUtils;
 
 /**
@@ -212,6 +214,78 @@ public class AbstractAuthenticationProcessingFilterTests {
 		assertThat(request.getSession()).isEqualTo(sessionPreAuth);
 	}
 
+	@Test
+	public void testNormalOperationWithDefaultFilterProcessesUrlAndAuthenticationManager() throws Exception {
+		// Setup our HTTP request
+		MockHttpServletRequest request = createMockAuthenticationRequest();
+		HttpSession sessionPreAuth = request.getSession();
+
+		// Setup our filter configuration
+		MockFilterConfig config = new MockFilterConfig(null, null);
+
+		// Setup our expectation that the filter chain will not be invoked, as we redirect
+		// to defaultTargetUrl
+		MockFilterChain chain = new MockFilterChain(false);
+		MockHttpServletResponse response = new MockHttpServletResponse();
+
+		// Setup our test object, to grant access
+		MockAuthenticationFilter filter = new MockAuthenticationFilter(
+				"/j_mock_post", mock(AuthenticationManager.class));
+
+		filter.setSessionAuthenticationStrategy(
+				mock(SessionAuthenticationStrategy.class));
+		filter.setAuthenticationSuccessHandler(successHandler);
+		filter.setAuthenticationFailureHandler(failureHandler);
+		filter.afterPropertiesSet();
+
+		// Test
+		filter.doFilter(request, response, chain);
+		assertThat(response.getRedirectedUrl()).isEqualTo("/mycontext/logged_in.jsp");
+		assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull();
+		assertThat(
+				SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()).isEqualTo(
+				"test");
+		// Should still have the same session
+		assertThat(request.getSession()).isEqualTo(sessionPreAuth);
+	}
+
+	@Test
+	public void testNormalOperationWithRequestMatcherAndAuthenticationManager() throws Exception {
+		// Setup our HTTP request
+		MockHttpServletRequest request = createMockAuthenticationRequest();
+		request.setServletPath("/j_eradicate_corona_virus");
+		request.setRequestURI("/mycontext/j_eradicate_corona_virus");
+		HttpSession sessionPreAuth = request.getSession();
+
+		// Setup our filter configuration
+		MockFilterConfig config = new MockFilterConfig(null, null);
+
+		// Setup our expectation that the filter chain will not be invoked, as we redirect
+		// to defaultTargetUrl
+		MockFilterChain chain = new MockFilterChain(false);
+		MockHttpServletResponse response = new MockHttpServletResponse();
+
+		// Setup our test object, to grant access
+		MockAuthenticationFilter filter = new MockAuthenticationFilter(
+				new AntPathRequestMatcher("/j_eradicate_corona_virus"), mock(AuthenticationManager.class));
+
+		filter.setSessionAuthenticationStrategy(
+				mock(SessionAuthenticationStrategy.class));
+		filter.setAuthenticationSuccessHandler(successHandler);
+		filter.setAuthenticationFailureHandler(failureHandler);
+		filter.afterPropertiesSet();
+
+		// Test
+		filter.doFilter(request, response, chain);
+		assertThat(response.getRedirectedUrl()).isEqualTo("/mycontext/logged_in.jsp");
+		assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull();
+		assertThat(
+				SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()).isEqualTo(
+				"test");
+		// Should still have the same session
+		assertThat(request.getSession()).isEqualTo(sessionPreAuth);
+	}
+
 	@Test
 	public void testStartupDetectsInvalidAuthenticationManager() {
 		AbstractAuthenticationProcessingFilter filter = new MockAuthenticationFilter();
@@ -430,20 +504,33 @@ public class AbstractAuthenticationProcessingFilterTests {
 	private class MockAuthenticationFilter
 			extends AbstractAuthenticationProcessingFilter {
 
+		private static final String DEFAULT_FILTER_PROCESSING_URL = "/j_mock_post";
+
 		private AuthenticationException exceptionToThrow;
 
 		private boolean grantAccess;
 
 		MockAuthenticationFilter(boolean grantAccess) {
 			this();
-			setRememberMeServices(new NullRememberMeServices());
+			setupRememberMeServicesAndAuthenticationException();
 			this.grantAccess = grantAccess;
-			this.exceptionToThrow = new BadCredentialsException(
-					"Mock requested to do so");
 		}
 
 		private MockAuthenticationFilter() {
-			super("/j_mock_post");
+			super(DEFAULT_FILTER_PROCESSING_URL);
+		}
+
+		private MockAuthenticationFilter(String defaultFilterProcessingUrl, AuthenticationManager authenticationManager) {
+			super(defaultFilterProcessingUrl, authenticationManager);
+			setupRememberMeServicesAndAuthenticationException();
+			this.grantAccess = true;
+		}
+
+		private MockAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher,
+				AuthenticationManager authenticationManager) {
+			super(requiresAuthenticationRequestMatcher, authenticationManager);
+			setupRememberMeServicesAndAuthenticationException();
+			this.grantAccess = true;
 		}
 
 		public Authentication attemptAuthentication(HttpServletRequest request,
@@ -456,6 +543,13 @@ public class AbstractAuthenticationProcessingFilterTests {
 				throw exceptionToThrow;
 			}
 		}
+
+		private void setupRememberMeServicesAndAuthenticationException() {
+			setRememberMeServices(new NullRememberMeServices());
+			this.exceptionToThrow = new BadCredentialsException(
+					"Mock requested to do so");
+		}
+
 	}
 
 	private class MockFilterChain implements FilterChain {

+ 17 - 0
web/src/test/java/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilterTests.java

@@ -57,6 +57,23 @@ public class UsernamePasswordAuthenticationFilterTests {
 		assertThat(((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()).isEqualTo("127.0.0.1");
 	}
 
+	@Test
+	public void testConstructorInjectionOfAuthenticationManager() {
+		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
+		request.addParameter(
+				UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY,
+				"rod");
+		request.addParameter(
+				UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY,
+				"dokdo");
+
+		UsernamePasswordAuthenticationFilter filter =
+				new UsernamePasswordAuthenticationFilter(createAuthenticationManager());
+
+		Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
+		assertThat(result).isNotNull();
+	}
+
 	@Test
 	public void testNullPasswordHandledGracefully() {
 		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");