diff --git a/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java b/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java index 17f0f6d871..7e39c27142 100755 --- a/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java +++ b/web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java @@ -116,6 +116,40 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi chain.doFilter(request, response); } + /** + * Determines if the current principal has changed. The default implementation tries + * + *
+ * Subclasses can override this method to determine when a principal has changed. + *
+ * + * @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. */ @@ -166,18 +200,11 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi return false; } - Object principal = getPreAuthenticatedPrincipal(request); - - if ((principal instanceof String) && currentUser.getName().equals(principal)) { + if(!principalChanged(request, currentUser)) { return false; } - if (principal != null && principal.equals(currentUser.getPrincipal())) { - return false; - } - - logger.debug("Pre-authenticated principal has changed to " + principal - + " and will be reauthenticated"); + logger.debug("Pre-authenticated principal has changed and will be reauthenticated"); if (invalidateSessionOnPrincipalChange) { SecurityContextHolder.clearContext(); diff --git a/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java index 3f70aff3dc..8cd4a2dbc4 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java @@ -274,6 +274,60 @@ public class AbstractPreAuthenticatedProcessingFilterTests { 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 { MockHttpServletRequest req = new MockHttpServletRequest(); MockHttpServletResponse res = new MockHttpServletResponse();