[[concurrency]] = Concurrency Support In most environments, Security is stored on a per-`Thread` basis. This means that when work is done on a new `Thread`, the `SecurityContext` is lost. Spring Security provides some infrastructure to help make this much easier to manage. Spring Security provides low-level abstractions for working with Spring Security in multi-threaded environments. In fact, this is what Spring Security builds on to integrate with xref:servlet/integrations/servlet-api.adoc#servletapi-start-runnable[`AsyncContext.start(Runnable)`] and xref:servlet/integrations/mvc.adoc#mvc-async[Spring MVC Async Integration]. == DelegatingSecurityContextRunnable One of the most fundamental building blocks within Spring Security's concurrency support is the `DelegatingSecurityContextRunnable`. It wraps a delegate `Runnable` to initialize the `SecurityContextHolder` with a specified `SecurityContext` for the delegate. It then invokes the delegate `Runnable`, ensuring to clear the `SecurityContextHolder` afterwards. The `DelegatingSecurityContextRunnable` looks something like this: ==== [source,java] ---- public void run() { try { SecurityContextHolder.setContext(securityContext); delegate.run(); } finally { SecurityContextHolder.clearContext(); } } ---- ==== While very simple, it makes it seamless to transfer the `SecurityContext` from one `Thread` to another. This is important since, in most cases, the `SecurityContextHolder` acts on a per-`Thread` basis. For example, you might have used Spring Security's xref:servlet/appendix/namespace/method-security.adoc#nsa-global-method-security[``] support to secure one of your services. You can now transfer the `SecurityContext` of the current `Thread` to the `Thread` that invokes the secured service. The following example show how you might do so: ==== [source,java] ---- Runnable originalRunnable = new Runnable() { public void run() { // invoke secured service } }; SecurityContext context = SecurityContextHolder.getContext(); DelegatingSecurityContextRunnable wrappedRunnable = new DelegatingSecurityContextRunnable(originalRunnable, context); new Thread(wrappedRunnable).start(); ---- ==== The preceding code: * Creates a `Runnable` that invokes our secured service. Note that it is not aware of Spring Security. * Obtains the `SecurityContext` that we wish to use from the `SecurityContextHolder` and initializes the `DelegatingSecurityContextRunnable`. * Uses the `DelegatingSecurityContextRunnable` to create a `Thread`. * Starts the `Thread` we created. Since it is common to create a `DelegatingSecurityContextRunnable` with the `SecurityContext` from the `SecurityContextHolder`, there is a shortcut constructor for it. The following code has the same effect as the preceding code: ==== [source,java] ---- Runnable originalRunnable = new Runnable() { public void run() { // invoke secured service } }; DelegatingSecurityContextRunnable wrappedRunnable = new DelegatingSecurityContextRunnable(originalRunnable); new Thread(wrappedRunnable).start(); ---- ==== The code we have is simple to use, but it still requires knowledge that we are using Spring Security. In the next section we will take a look at how we can utilize `DelegatingSecurityContextExecutor` to hide the fact that we are using Spring Security. == DelegatingSecurityContextExecutor In the previous section, we found that it was easy to use the `DelegatingSecurityContextRunnable`, but it was not ideal since we had to be aware of Spring Security to use it. Now we look at how `DelegatingSecurityContextExecutor` can shield our code from any knowledge that we are using Spring Security. The design of `DelegatingSecurityContextExecutor` is similar to that of `DelegatingSecurityContextRunnable`, except that it accepts a delegate `Executor` instead of a delegate `Runnable`. The following example shows how to use it: ==== [source,java] ---- SecurityContext context = SecurityContextHolder.createEmptyContext(); Authentication authentication = UsernamePasswordAuthenticationToken.authenticated("user","doesnotmatter", AuthorityUtils.createAuthorityList("ROLE_USER")); context.setAuthentication(authentication); SimpleAsyncTaskExecutor delegateExecutor = new SimpleAsyncTaskExecutor(); DelegatingSecurityContextExecutor executor = new DelegatingSecurityContextExecutor(delegateExecutor, context); Runnable originalRunnable = new Runnable() { public void run() { // invoke secured service } }; executor.execute(originalRunnable); ---- ==== This code: Note that, in this example, we create the `SecurityContext` by hand. However, it does not matter where or how we get the `SecurityContext` (for example, we could obtain it from the `SecurityContextHolder`). * Creates a `delegateExecutor` that is in charge of executing submitted `Runnable` objects. * Finally, we create a `DelegatingSecurityContextExecutor`, which is in charge of wrapping any `Runnable` that is passed into the `execute` method with a `DelegatingSecurityContextRunnable`. It then passes the wrapped `Runnable` to the `delegateExecutor`. In this case, the same `SecurityContext` is used for every `Runnable` submitted to our `DelegatingSecurityContextExecutor`. This is nice if we run background tasks that need to be run by a user with elevated privileges. * At this point, you may ask yourself, "`How does this shield my code of any knowledge of Spring Security?`" Instead of creating the `SecurityContext` and the `DelegatingSecurityContextExecutor` in our own code, we can inject an already initialized instance of `DelegatingSecurityContextExecutor`. Consider the following example: ==== [source,java] ---- @Autowired private Executor executor; // becomes an instance of our DelegatingSecurityContextExecutor public void submitRunnable() { Runnable originalRunnable = new Runnable() { public void run() { // invoke secured service } }; executor.execute(originalRunnable); } ---- ==== Now our code is unaware that the `SecurityContext` is being propagated to the `Thread`, the `originalRunnable` is run, and the `SecurityContextHolder` is cleared out. In this example, the same user is being used to run each thread. What if we wanted to use the user from `SecurityContextHolder` (that is, the currently logged in-user) at the time we invoked `executor.execute(Runnable)` to process `originalRunnable`? You can do so by removing the `SecurityContext` argument from our `DelegatingSecurityContextExecutor` constructor: ==== [source,java] ---- SimpleAsyncTaskExecutor delegateExecutor = new SimpleAsyncTaskExecutor(); DelegatingSecurityContextExecutor executor = new DelegatingSecurityContextExecutor(delegateExecutor); ---- ==== Now, any time `executor.execute(Runnable)` is run, the `SecurityContext` is first obtained by the `SecurityContextHolder` and then that `SecurityContext` is used to create our `DelegatingSecurityContextRunnable`. This means that we are running our `Runnable` with the same user that was used to invoke the `executor.execute(Runnable)` code. == Spring Security Concurrency Classes See the {security-api-url}index.html[Javadoc] for additional integrations with both the Java concurrent APIs and the Spring Task abstractions. They are self-explanatory once you understand the previous code. * {security-api-url}org/springframework/security/concurrent/DelegatingSecurityContextCallable.html[`DelegatingSecurityContextCallable`] * {security-api-url}org/springframework/security/concurrent/DelegatingSecurityContextExecutor.html[`DelegatingSecurityContextExecutor`] * {security-api-url}org/springframework/security/concurrent/DelegatingSecurityContextExecutorService.html[`DelegatingSecurityContextExecutorService`] * {security-api-url}org/springframework/security/concurrent/DelegatingSecurityContextRunnable.html[`DelegatingSecurityContextRunnable`] * {security-api-url}org/springframework/security/concurrent/DelegatingSecurityContextScheduledExecutorService.html[`DelegatingSecurityContextScheduledExecutorService`] * {security-api-url}org/springframework/security/scheduling/DelegatingSecurityContextSchedulingTaskExecutor.html[`DelegatingSecurityContextSchedulingTaskExecutor`] * {security-api-url}org/springframework/security/task/DelegatingSecurityContextAsyncTaskExecutor.html[`DelegatingSecurityContextAsyncTaskExecutor`] * {security-api-url}org/springframework/security/task/DelegatingSecurityContextTaskExecutor.html[`DelegatingSecurityContextTaskExecutor`] * {security-api-url}org/springframework/security/scheduling/DelegatingSecurityContextTaskScheduler.html[`DelegatingSecurityContextTaskScheduler`]