Skip to content

Allow override AbstractPreAuthenticatedProcessingFilter#requiresAuthentication #5928

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
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;

Expand Down Expand Up @@ -73,6 +74,7 @@
* @author Luke Taylor
* @author Ruud Senden
* @author Rob Winch
* @author Tadaya Tsuyukubo
* @since 2.0
*/
public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFilterBean
Expand All @@ -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.
Expand Down Expand Up @@ -114,7 +117,7 @@ public void doFilter(ServletRequest request, ServletResponse response,
+ SecurityContextHolder.getContext().getAuthentication());
}

if (requiresAuthentication((HttpServletRequest) request)) {
if (requiresAuthenticationRequestMatcher.matches((HttpServletRequest) request)) {
doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response);
}

Expand Down Expand Up @@ -193,39 +196,6 @@ private void doAuthenticate(HttpServletRequest request, HttpServletResponse resp
}
}

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.
Expand Down Expand Up @@ -348,6 +318,14 @@ public void setAuthenticationFailureHandler(AuthenticationFailureHandler authent
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
*/
Expand All @@ -359,4 +337,46 @@ public void setAuthenticationFailureHandler(AuthenticationFailureHandler authent
* 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;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@
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 {
Expand Down Expand Up @@ -377,6 +379,43 @@ protected boolean principalChanged(HttpServletRequest request,
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();
Expand Down