SEC-1998: SecurityContextCallableProcessingInterceptor uses postProcess

Previously SecurityContextCallableProcessingInterceptor used afterCompletion
to clear the SecurityContextHolder. This does not work since afterCompletion
is invoked on the Servlet Container thread.

Now SecurityContextCallableProcessingInterceptor clears the
SecurityContextHolder on postProcess which is invoked on the same thread
that the Callable is processed on.
This commit is contained in:
Rob Winch 2012-12-06 12:59:21 -06:00
parent 796de42105
commit 3437ef714a
3 changed files with 23 additions and 7 deletions

View File

@ -29,7 +29,7 @@ import org.springframework.web.context.request.async.CallableProcessingIntercept
* A {@link CallableProcessingInterceptor} that establishes the injected {@link SecurityContext} on the
* {@link SecurityContextHolder} when {@link #preProcess(NativeWebRequest, Callable)} is invoked. It also clear out the
* {@link SecurityContextHolder} by invoking {@link SecurityContextHolder#clearContext()} in the
* {@link #afterCompletion(NativeWebRequest, Callable)} method.
* {@link #postProcess(NativeWebRequest, Callable, Object)} method.
* </p>
*
* @author Rob Winch
@ -64,13 +64,13 @@ public final class SecurityContextCallableProcessingInterceptor extends Callable
}
@Override
public <T> void afterCompletion(NativeWebRequest request, Callable<T> task) throws Exception {
SecurityContextHolder.clearContext();
public <T> void preProcess(NativeWebRequest request, Callable<T> task) throws Exception {
SecurityContextHolder.setContext(securityContext);
}
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) throws Exception {
SecurityContextHolder.setContext(securityContext);
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) throws Exception {
SecurityContextHolder.clearContext();
}
private void setSecurityContext(SecurityContext securityContext) {

View File

@ -59,7 +59,7 @@ public class SecurityContextCallableProcessingInterceptorTests {
interceptor.preProcess(webRequest, callable);
assertThat(SecurityContextHolder.getContext()).isSameAs(securityContext);
interceptor.afterCompletion(webRequest, callable);
interceptor.postProcess(webRequest, callable, null);
assertThat(SecurityContextHolder.getContext()).isNotSameAs(securityContext);
}
@ -71,7 +71,7 @@ public class SecurityContextCallableProcessingInterceptorTests {
interceptor.preProcess(webRequest, callable);
assertThat(SecurityContextHolder.getContext()).isSameAs(securityContext);
interceptor.afterCompletion(webRequest, callable);
interceptor.postProcess(webRequest, callable, null);
assertThat(SecurityContextHolder.getContext()).isNotSameAs(securityContext);
}
}

View File

@ -31,7 +31,9 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.async.AsyncWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
@ -84,6 +86,13 @@ public class WebAsyncManagerIntegrationFilterTests {
@Test
public void doFilterInternalRegistersSecurityContextCallableProcessor() throws Exception {
SecurityContextHolder.setContext(securityContext);
asyncManager.registerCallableInterceptors(new CallableProcessingInterceptorAdapter() {
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult)
throws Exception {
assertThat(SecurityContextHolder.getContext()).isNotSameAs(securityContext);
}
});
filter.doFilterInternal(request, response, filterChain);
VerifyingCallable verifyingCallable = new VerifyingCallable();
@ -95,6 +104,13 @@ public class WebAsyncManagerIntegrationFilterTests {
@Test
public void doFilterInternalRegistersSecurityContextCallableProcessorContextUpdated() throws Exception {
SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
asyncManager.registerCallableInterceptors(new CallableProcessingInterceptorAdapter() {
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult)
throws Exception {
assertThat(SecurityContextHolder.getContext()).isNotSameAs(securityContext);
}
});
filter.doFilterInternal(request, response, filterChain);
SecurityContextHolder.setContext(securityContext);