Add constructors to AbstractAuthenticationProcessingFilter

Closes gh-8309
This commit is contained in:
Oh Myung Woon 2020-04-09 22:25:55 +09:00 committed by Rob Winch
parent 419d7264f9
commit b7d3acc02c
4 changed files with 150 additions and 5 deletions

View File

@ -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
// ========================================================================================================

View File

@ -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

View File

@ -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 {

View File

@ -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", "/");