Add Support for AuthenticationConverter

Closes gh-16793
This commit is contained in:
Josh Cummings 2025-03-20 17:14:35 -06:00
parent 90dd31cae5
commit 8199015e79
No known key found for this signature in database
GPG Key ID: 869B37A20E876129

View File

@ -31,6 +31,7 @@ import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.core.log.LogMessage;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
@ -122,6 +123,11 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
protected AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
private AuthenticationConverter authenticationConverter = (request) -> {
throw new AuthenticationCredentialsNotFoundException(
"Please either configure an AuthenticationConverter or override attemptAuthentication when extending AbstractAuthenticationProcessingFilter");
};
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
@ -132,6 +138,8 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
private boolean continueChainBeforeSuccessfulAuthentication = false;
private boolean continueChainWhenNoAuthenticationResult;
private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
private boolean allowSessionCreation = true;
@ -230,6 +238,10 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
try {
Authentication authenticationResult = attemptAuthentication(request, response);
if (authenticationResult == null) {
if (this.continueChainWhenNoAuthenticationResult) {
chain.doFilter(request, response);
return;
}
// return immediately as subclass has indicated that it hasn't completed
return;
}
@ -292,8 +304,18 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
* @return the authenticated user token, or null if authentication is incomplete.
* @throws AuthenticationException if authentication fails.
*/
public abstract Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException;
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
Authentication authentication = this.authenticationConverter.convert(request);
if (authentication == null) {
return null;
}
Authentication result = this.authenticationManager.authenticate(authentication);
if (result == null) {
throw new ServletException("AuthenticationManager should not return null Authentication object.");
}
return result;
}
/**
* Default behaviour for successful authentication.
@ -354,6 +376,12 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
this.failureHandler.onAuthenticationFailure(request, response, failed);
}
public void setAuthenticationConverter(AuthenticationConverter authenticationConverter) {
Assert.notNull(authenticationConverter, "authenticationConverter cannot be null");
this.authenticationConverter = authenticationConverter;
this.continueChainWhenNoAuthenticationResult = true;
}
protected AuthenticationManager getAuthenticationManager() {
return this.authenticationManager;
}