I asynchronously invoke method with Spring, using @Async.This method invokes other method annotated with @PreAuthorize, Spring Security Annotation. To make authorization works I have to set SecurityContextHolder
mode to MODE_INHERITABLETHREADLOCAL
, so that authentication info is passed to the asynchronous call. Everything works fine so far.
However when I logout and login as a different user, in asynchronous method SecurityContextHolder stores authentication info of the old user, that has bee logged out. It causes of course unwanted AccessDenied
exception. There is no such problem with synchronous calls.
I have defined <task:executor id="executors" pool-size="10"/>
, so may it be a problem that once thread in executors pool has been initialized it will not override authentication information?
Jus to add to the answer from @axtavt, you would also want to override other method.
I guess
MODE_INHERITABLETHREADLOCAL
doesn't work correctly with thread pool.As a possible solution you can try to subclass
ThreadPoolTaskExecutor
and override its methods to propagateSecurityContext
manually, and then declare that executor instead of<task:executor>
, something like this:Using the information from Ralph and Oak -
If you want to get @Async working with the standard task executor tag, you would set up your Spring XML config like this
Then in your @Async method, you would specify the pool you want to use
That should work so when whenever you call your @Async method, the threadpool thread will use the same security context as the calling thread
This is just a hint that needs future investigation (I am too tired, but maybe somebody find this useful for future investigation):
Today I stumbled over
org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor
see GitHub.it looks like that his designed to delegate the security context so that it is "passed" through the
@Async
call.Also have a look at this post: Spring Security 3.2 M1 Highlights, Servlet 3 API Support is sounds like it is strongly related.
Based on @Ralph answer one can achieve
Aync event
withSpring
withthreadpooling
and delegate the security using http://docs.spring.io/autorepo/docs/spring-security/4.0.0.M1/apidocs/org/springframework/security/task/DelegatingSecurityContextAsyncTaskExecutor.htmlSample code