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 continueFilterChainOnUnsuccessfulAuthentication = true;
|
||||||
|
|
||||||
|
private boolean checkForPrincipalChanges;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether all required properties have been set.
|
* 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());
|
logger.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
if (requiresAuthentication((HttpServletRequest) request)) {
|
||||||
doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response);
|
doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response);
|
||||||
}
|
}
|
||||||
|
|
||||||
chain.doFilter(request, 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
|
* Puts the <code>Authentication</code> instance returned by the
|
||||||
* authentication manager into the secure context.
|
* authentication manager into the secure context.
|
||||||
|
@ -165,6 +186,17 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||||
continueFilterChainOnUnsuccessfulAuthentication = shouldContinue;
|
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
|
* Override to extract the principal information from the current request
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -87,6 +87,30 @@ public class RequestHeaderPreAuthenticatedProcessingFilterTests {
|
||||||
assertEquals("catspassword", SecurityContextHolder.getContext().getAuthentication().getCredentials());
|
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() {
|
private AuthenticationManager createAuthenticationManager() {
|
||||||
AuthenticationManager am = mock(AuthenticationManager.class);
|
AuthenticationManager am = mock(AuthenticationManager.class);
|
||||||
when(am.authenticate(any(Authentication.class))).thenAnswer(new Answer<Authentication>() {
|
when(am.authenticate(any(Authentication.class))).thenAnswer(new Answer<Authentication>() {
|
||||||
|
|
Loading…
Reference in New Issue