Add property to stop filter chain after successful authentication

Closes gh-96
Closes gh-97
This commit is contained in:
Rob Winch
2024-05-29 17:24:39 -05:00
parent 50a77ae051
commit da703aa449
2 changed files with 54 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -100,6 +100,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
*
* @author Mike Wiesner
* @author Jeremy Stone
* @author Denis Angilella
* @since 1.0
* @see KerberosServiceAuthenticationProvider
* @see SpnegoEntryPoint
@@ -112,6 +113,7 @@ public class SpnegoAuthenticationProcessingFilter extends OncePerRequestFilter {
private AuthenticationFailureHandler failureHandler;
private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
private boolean skipIfAlreadyAuthenticated = true;
private boolean stopFilterChainOnSuccessfulAuthentication = false;
/**
* Authentication header prefix sent by IE/Windows when the domain controller fails to issue a Kerberos
@@ -166,7 +168,9 @@ public class SpnegoAuthenticationProcessingFilter extends OncePerRequestFilter {
if (successHandler != null) {
successHandler.onAuthenticationSuccess(request, response, authentication);
}
if (stopFilterChainOnSuccessfulAuthentication) {
return;
}
}
chain.doFilter(request, response);
@@ -249,4 +253,15 @@ public class SpnegoAuthenticationProcessingFilter extends OncePerRequestFilter {
this.authenticationDetailsSource = authenticationDetailsSource;
}
/**
* If set to {@code false} (the default) and authentication is successful, the request will be processed by
* the next filter in the chain. If {@code true} and authentication is successful, the filter chain will stop here.
*
* @since 1.0.2
* @param shouldStop set to {@code true} to prevent the next filter in the chain from processing the request
* after a successful authentication.
*/
public void setStopFilterChainOnSuccessfulAuthentication(boolean shouldStop) {
this.stopFilterChainOnSuccessfulAuthentication = shouldStop;
}
}

View File

@@ -133,23 +133,24 @@ public class SpnegoAuthenticationProcessingFilterTest {
private void everythingWorksWithHandlers(String tokenPrefix) throws Exception {
createHandler();
everythingWorks(tokenPrefix);
verify(successHandler).onAuthenticationSuccess(request, response, AUTHENTICATION);
verify(failureHandler, never()).onAuthenticationFailure(any(HttpServletRequest.class),
everythingWorksVerifyHandlers();
}
private void everythingWorksVerifyHandlers() throws Exception {
verify(successHandler).onAuthenticationSuccess(request, response, AUTHENTICATION);
verify(failureHandler, never()).onAuthenticationFailure(any(HttpServletRequest.class),
any(HttpServletResponse.class), any(AuthenticationException.class));
}
private void everythingWorks(String tokenPrefix) throws IOException,
ServletException {
// stubbing
when(request.getHeader(HEADER)).thenReturn(tokenPrefix + TEST_TOKEN_BASE64);
KerberosServiceRequestToken requestToken = new KerberosServiceRequestToken(TEST_TOKEN);
requestToken.setDetails(detailsSource.buildDetails(request));
when(authenticationManager.authenticate(requestToken)).thenReturn(AUTHENTICATION);
everythingWorksStub(tokenPrefix);
// testing
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication());
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication());
}
@Test
@@ -184,12 +185,12 @@ public class SpnegoAuthenticationProcessingFilterTest {
@Test
public void testAuthenticationFailsWithHandlers() throws Exception {
createHandler();
authenticationFails();
verify(failureHandler).onAuthenticationFailure(request, response, BCE);
verify(successHandler, never()).onAuthenticationSuccess(any(HttpServletRequest.class),
any(HttpServletResponse.class), any(Authentication.class));
verify(response, never()).setStatus(anyInt());
createHandler();
authenticationFails();
verify(failureHandler).onAuthenticationFailure(request, response, BCE);
verify(successHandler, never()).onAuthenticationSuccess(any(HttpServletRequest.class),
any(HttpServletResponse.class), any(Authentication.class));
verify(response, never()).setStatus(anyInt());
}
@Test
@@ -248,6 +249,27 @@ public class SpnegoAuthenticationProcessingFilterTest {
}
}
@Test
public void testEverythingWorksWithHandlers_stopFilterChain() throws Exception {
filter.setStopFilterChainOnSuccessfulAuthentication(true);
createHandler();
everythingWorksStub(TOKEN_PREFIX_NEG);
// testing
filter.doFilter(request, response, chain);
verify(chain, never()).doFilter(request, response);
assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication());
everythingWorksVerifyHandlers();
}
private void everythingWorksStub(String tokenPrefix) throws IOException, ServletException {
when(request.getHeader(HEADER)).thenReturn(tokenPrefix + TEST_TOKEN_BASE64);
KerberosServiceRequestToken requestToken = new KerberosServiceRequestToken(TEST_TOKEN);
requestToken.setDetails(detailsSource.buildDetails(request));
when(authenticationManager.authenticate(requestToken)).thenReturn(AUTHENTICATION);
}
private void authenticationFails() throws IOException, ServletException {
// stubbing
when(request.getHeader(HEADER)).thenReturn(TOKEN_PREFIX_NEG + TEST_TOKEN_BASE64);