diff --git a/core/src/main/java/org/springframework/security/intercept/AbstractSecurityInterceptor.java b/core/src/main/java/org/springframework/security/intercept/AbstractSecurityInterceptor.java index 01a026ba5c..6104f073ad 100644 --- a/core/src/main/java/org/springframework/security/intercept/AbstractSecurityInterceptor.java +++ b/core/src/main/java/org/springframework/security/intercept/AbstractSecurityInterceptor.java @@ -26,8 +26,10 @@ import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.RunAsManager; +import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.context.SecurityContextImpl; import org.springframework.security.event.authorization.AuthenticationCredentialsNotFoundEvent; import org.springframework.security.event.authorization.AuthorizationFailureEvent; import org.springframework.security.event.authorization.AuthorizedEvent; @@ -110,7 +112,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A protected static final Log logger = LogFactory.getLog(AbstractSecurityInterceptor.class); //~ Instance fields ================================================================================================ - + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private ApplicationEventPublisher eventPublisher; private AccessDecisionManager accessDecisionManager; @@ -140,21 +142,22 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A if (token.isContextHolderRefreshRequired()) { if (logger.isDebugEnabled()) { - logger.debug("Reverting to original Authentication: " + token.getAuthentication().toString()); + logger.debug("Reverting to original Authentication: " + token.getSecurityContext().getAuthentication()); } - SecurityContextHolder.getContext().setAuthentication(token.getAuthentication()); + SecurityContextHolder.setContext(token.getSecurityContext()); } if (afterInvocationManager != null) { // Attempt after invocation handling try { - returnedObject = afterInvocationManager.decide(token.getAuthentication(), token.getSecureObject(), + returnedObject = afterInvocationManager.decide(token.getSecurityContext().getAuthentication(), + token.getSecureObject(), token.getAttr(), returnedObject); } catch (AccessDeniedException accessDeniedException) { AuthorizationFailureEvent event = new AuthorizationFailureEvent(token.getSecureObject(), token - .getAttr(), token.getAuthentication(), accessDeniedException); + .getAttr(), token.getSecurityContext().getAuthentication(), accessDeniedException); publishEvent(event); throw accessDeniedException; @@ -285,16 +288,20 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A } // no further work post-invocation - return new InterceptorStatusToken(authenticated, false, attr, object); + return new InterceptorStatusToken(SecurityContextHolder.getContext(), false, attr, object); } else { if (logger.isDebugEnabled()) { logger.debug("Switching to RunAs Authentication: " + runAs); } - SecurityContextHolder.getContext().setAuthentication(runAs); + SecurityContext originalContext = SecurityContextHolder.getContext(); + SecurityContext runAsContext = new SecurityContextImpl(); + runAsContext.setAuthentication(runAs); - // revert to token.Authenticated post-invocation - return new InterceptorStatusToken(authenticated, true, attr, object); + SecurityContextHolder.setContext(runAsContext); + + // revert to original context post-invocation + return new InterceptorStatusToken(originalContext, true, attr, object); } } diff --git a/core/src/main/java/org/springframework/security/intercept/InterceptorStatusToken.java b/core/src/main/java/org/springframework/security/intercept/InterceptorStatusToken.java index 210a31c23d..b711ee81c6 100644 --- a/core/src/main/java/org/springframework/security/intercept/InterceptorStatusToken.java +++ b/core/src/main/java/org/springframework/security/intercept/InterceptorStatusToken.java @@ -17,6 +17,7 @@ package org.springframework.security.intercept; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttributeDefinition; +import org.springframework.security.context.SecurityContext; /** @@ -32,16 +33,16 @@ import org.springframework.security.ConfigAttributeDefinition; public class InterceptorStatusToken { //~ Instance fields ================================================================================================ - private Authentication authentication; + private SecurityContext context; private ConfigAttributeDefinition attr; private Object secureObject; private boolean contextHolderRefreshRequired; //~ Constructors =================================================================================================== - public InterceptorStatusToken(Authentication authentication, boolean contextHolderRefreshRequired, + public InterceptorStatusToken(SecurityContext context, boolean contextHolderRefreshRequired, ConfigAttributeDefinition attr, Object secureObject) { - this.authentication = authentication; + this.context = context; this.contextHolderRefreshRequired = contextHolderRefreshRequired; this.attr = attr; this.secureObject = secureObject; @@ -53,8 +54,8 @@ public class InterceptorStatusToken { return attr; } - public Authentication getAuthentication() { - return authentication; + public SecurityContext getSecurityContext() { + return context; } public Object getSecureObject() { diff --git a/core/src/test/java/org/springframework/security/intercept/InterceptorStatusTokenTests.java b/core/src/test/java/org/springframework/security/intercept/InterceptorStatusTokenTests.java index 5b121b665c..c9baf08c9e 100644 --- a/core/src/test/java/org/springframework/security/intercept/InterceptorStatusTokenTests.java +++ b/core/src/test/java/org/springframework/security/intercept/InterceptorStatusTokenTests.java @@ -18,6 +18,8 @@ package org.springframework.security.intercept; import junit.framework.TestCase; import org.springframework.security.ConfigAttributeDefinition; +import org.springframework.security.context.SecurityContext; +import org.springframework.security.context.SecurityContextImpl; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.util.SimpleMethodInvocation; @@ -58,12 +60,13 @@ public class InterceptorStatusTokenTests extends TestCase { ConfigAttributeDefinition attr = new ConfigAttributeDefinition("FOO"); MethodInvocation mi = new SimpleMethodInvocation(); - InterceptorStatusToken token = new InterceptorStatusToken(new UsernamePasswordAuthenticationToken("rod", - "koala"), true, attr, mi); + SecurityContext ctx = new SecurityContextImpl(); + + InterceptorStatusToken token = new InterceptorStatusToken(ctx, true, attr, mi); assertTrue(token.isContextHolderRefreshRequired()); assertEquals(attr, token.getAttr()); assertEquals(mi, token.getSecureObject()); - assertEquals("rod", token.getAuthentication().getPrincipal()); + assertSame(ctx, token.getSecurityContext()); } } diff --git a/core/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorTests.java b/core/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorTests.java index 1f07e6e4ae..33211f7a63 100644 --- a/core/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorTests.java @@ -34,6 +34,7 @@ import org.springframework.security.MockAuthenticationManager; import org.springframework.security.MockRunAsManager; import org.springframework.security.RunAsManager; +import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.intercept.method.MethodDefinitionSource; @@ -166,11 +167,15 @@ public class MethodSecurityInterceptorTests extends TestCase { public void testMethodCallWithRunAsReplacement() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_UPPER")}); - SecurityContextHolder.getContext().setAuthentication(token); + SecurityContext ctx = SecurityContextHolder.getContext(); + ctx.setAuthentication(token); ITargetObject target = makeInterceptedTarget(); String result = target.makeUpperCase("hello"); assertEquals("HELLO org.springframework.security.MockRunAsAuthenticationToken true", result); + // Check reset afterwards + assertSame(ctx, SecurityContextHolder.getContext()); + assertSame(token, SecurityContextHolder.getContext().getAuthentication()); } public void testMethodCallWithoutRunAsReplacement()