SEC-1190: Added "checkForPrincipalChanges" property to AbstactPreAuthenticatedProcessingFilter.
This commit is contained in:
parent
dbcb13ad14
commit
3cc47c9c4d
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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>() {
|
||||
|
|
Loading…
Reference in New Issue