SEC-3051: Add AbstractPreAuthenticatedProcessingFilter#principalChanged

This commit is contained in:
Rob Winch 2015-07-22 08:41:33 -05:00
parent a50d297f3a
commit 92ae45a04d
2 changed files with 90 additions and 9 deletions

View File

@ -116,6 +116,40 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
chain.doFilter(request, response); chain.doFilter(request, response);
} }
/**
* Determines if the current principal has changed. The default implementation tries
*
* <ul>
* <li>If the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is a String, the {@link Authentication#getName()} is compared against the pre authenticated principal</li>
* <li>Otherwise, the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is compared against the {@link Authentication#getPrincipal()}
* </ul>
*
* <p>
* Subclasses can override this method to determine when a principal has changed.
* </p>
*
* @param request
* @param currentAuthentication
* @return true if the principal has changed, else false
*/
protected boolean principalChanged(HttpServletRequest request, Authentication currentAuthentication) {
Object principal = getPreAuthenticatedPrincipal(request);
if ((principal instanceof String) && currentAuthentication.getName().equals(principal)) {
return false;
}
if (principal != null && principal.equals(currentAuthentication.getPrincipal())) {
return false;
}
if(logger.isDebugEnabled()) {
logger.debug("Pre-authenticated principal has changed to " + principal + " and will be reauthenticated");
}
return true;
}
/** /**
* Do the actual authentication for a pre-authenticated user. * Do the actual authentication for a pre-authenticated user.
*/ */
@ -166,18 +200,11 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
return false; return false;
} }
Object principal = getPreAuthenticatedPrincipal(request); if(!principalChanged(request, currentUser)) {
if ((principal instanceof String) && currentUser.getName().equals(principal)) {
return false; return false;
} }
if (principal != null && principal.equals(currentUser.getPrincipal())) { logger.debug("Pre-authenticated principal has changed and will be reauthenticated");
return false;
}
logger.debug("Pre-authenticated principal has changed to " + principal
+ " and will be reauthenticated");
if (invalidateSessionOnPrincipalChange) { if (invalidateSessionOnPrincipalChange) {
SecurityContextHolder.clearContext(); SecurityContextHolder.clearContext();

View File

@ -274,6 +274,60 @@ public class AbstractPreAuthenticatedProcessingFilterTests {
verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class)); verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class));
} }
@Test
public void requiresAuthenticationOverridePrincipalChangedTrue() throws Exception {
Object principal = new Object();
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken(principal, "something", "ROLE_USER"));
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain();
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter() {
@Override
protected boolean principalChanged(HttpServletRequest request,
Authentication currentAuthentication) {
return true;
}
};
filter.setCheckForPrincipalChanges(true);
filter.principal = principal;
AuthenticationManager am = mock(AuthenticationManager.class);
filter.setAuthenticationManager(am);
filter.afterPropertiesSet();
filter.doFilter(request, response, chain);
verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class));
}
@Test
public void requiresAuthenticationOverridePrincipalChangedFalse() throws Exception {
Object principal = new Object();
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken(principal, "something", "ROLE_USER"));
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain();
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter() {
@Override
protected boolean principalChanged(HttpServletRequest request,
Authentication currentAuthentication) {
return false;
}
};
filter.setCheckForPrincipalChanges(true);
filter.principal = principal;
AuthenticationManager am = mock(AuthenticationManager.class);
filter.setAuthenticationManager(am);
filter.afterPropertiesSet();
filter.doFilter(request, response, chain);
verifyZeroInteractions(am);
}
private void testDoFilter(boolean grantAccess) throws Exception { private void testDoFilter(boolean grantAccess) throws Exception {
MockHttpServletRequest req = new MockHttpServletRequest(); MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse(); MockHttpServletResponse res = new MockHttpServletResponse();