SEC-1190: Added "checkForPrincipalChanges" property to AbstactPreAuthenticatedProcessingFilter.

This commit is contained in:
Luke Taylor 2009-08-31 23:28:40 +00:00
parent dbcb13ad14
commit 3cc47c9c4d
2 changed files with 57 additions and 1 deletions

View File

@ -49,6 +49,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
private boolean continueFilterChainOnUnsuccessfulAuthentication = true;
private boolean checkForPrincipalChanges;
/**
* Check whether all required properties have been set.
*/
@ -67,9 +69,10 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
logger.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication());
}
if (SecurityContextHolder.getContext().getAuthentication() == null) {
if (requiresAuthentication((HttpServletRequest) request)) {
doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response);
}
chain.doFilter(request, response);
}
@ -108,6 +111,24 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
}
}
private boolean requiresAuthentication(HttpServletRequest request) {
Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
if (currentUser == null) {
return true;
}
Object principal = getPreAuthenticatedPrincipal(request);
if (checkForPrincipalChanges &&
!currentUser.getName().equals(principal)) {
logger.debug("Pre-authenticated principal has changed to " + principal + " and will be reauthenticated");
return true;
}
return false;
}
/**
* Puts the <code>Authentication</code> instance returned by the
* authentication manager into the secure context.
@ -165,6 +186,17 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
continueFilterChainOnUnsuccessfulAuthentication = shouldContinue;
}
/**
* If set, the pre-authenticated principal will be checked on each request and compared
* against the name of the current <tt>Authentication</tt> object. If a change is detected,
* the user will be reauthenticated.
*
* @param checkForPrincipalChanges
*/
public void setCheckForPrincipalChanges(boolean checkForPrincipalChanges) {
this.checkForPrincipalChanges = checkForPrincipalChanges;
}
/**
* Override to extract the principal information from the current request
*/

View File

@ -87,6 +87,30 @@ public class RequestHeaderPreAuthenticatedProcessingFilterTests {
assertEquals("catspassword", SecurityContextHolder.getContext().getAuthentication().getCredentials());
}
@Test
public void userIsReauthenticatedIfPrincipalChangesAndCheckForPrincipalChangesIsSet() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
RequestHeaderPreAuthenticatedProcessingFilter filter = new RequestHeaderPreAuthenticatedProcessingFilter();
filter.setAuthenticationManager(createAuthenticationManager());
filter.setCheckForPrincipalChanges(true);
request.addHeader("SM_USER", "cat");
filter.doFilter(request, response, new MockFilterChain());
request = new MockHttpServletRequest();
request.addHeader("SM_USER", "dog");
filter.doFilter(request, response, new MockFilterChain());
Authentication dog = SecurityContextHolder.getContext().getAuthentication();
assertNotNull(dog);
assertEquals("dog", dog.getName());
// Make sure authentication doesn't occur every time (i.e. if the header *doesn't change)
filter.setAuthenticationManager(mock(AuthenticationManager.class));
filter.doFilter(request, response, new MockFilterChain());
assertSame(dog, SecurityContextHolder.getContext().getAuthentication());
}
/**
* Create an authentication manager which returns the passed in object.
*/
private AuthenticationManager createAuthenticationManager() {
AuthenticationManager am = mock(AuthenticationManager.class);
when(am.authenticate(any(Authentication.class))).thenAnswer(new Answer<Authentication>() {