Spring Security 3.2 M1 Highlights, Servlet 3 API Support |

Last week I announced the release of Spring Security 3.2 M1 that contains improved Servlet 3 support. In this post, I will introduce some of the more exciting features found in the 3.2 M1 release. Specifically, we will take a look at the following new Spring Security features:
Concurrency Support
You might ask "What is concurrency support doing in a release that has a Servlet 3 focused theme?" The reason is that the concurrency support provides a foundation for all the other features found in this release. While the concurrency support is used by the Servlet 3 integration, it can also serve as building blocks to support concurrency and Spring Security in any application. Let's take a look at Spring Security's concurrency support now.
DelegatingSecurityContextRunnable
One of the most fundamental building blocks within Spring Security's concurrency support is the DelegatingSecurityContextRunnable. It wraps a delegate Runnable in order 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:
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 <global-method-security> support to secure one of your services. You can now easily transfer the SecurityContext of the current Thread to the Thread that invokes the secured service. An example of how you might do this can be found below:
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 code above performs the following steps:
- Creates a
Runnablethat will be invoking our secured service. Notice that it is not aware of Spring Security - Obtains the
SecurityContextthat we wish to use from theSecurityContextHolderand initializes theDelegatingSecurityContextRunnable - Use the
DelegatingSecurityContextRunnableto create aThread - Start the
Threadwe created
Since it is quite common to create a DelegatingSecurityContextRunnable with the SecurityContext from the SecurityContextHolder there is a shortcut constructor for it. The following code is the same as the code above:
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 in order to use it. Let's take a look at how DelegatingSecurityContextExecutor can shield our code from any knowledge that we are using Spring Security.
The design of DelegatingSecurityContextExecutor is very similar to that of DelegatingSecurityContextRunnable except it accepts a delegate Executor instead of a delegate Runnable. You can see an example of how it might be used below:
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication =
new UsernamePasswordAuthenticationToken("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);
The code performs the following steps:
- Creates the
SecurityContextto be used for ourDelegatingSecurityContextExecutor. Note that in this example we simply create theSecurityContextby hand. However, it does not matter where or how we get theSecurityContext(i.e. we could obtain it from theSecurityContextHolderif we wanted). - Creates a delegateExecutor that is in charge of executing submitted
Runnables - Finally we create a
DelegatingSecurityContextExecutorwhich is in charge of wrapping anyRunnablethat is passed into the execute method with aDelegatingSecurityContextRunnable. It then passes the wrappedRunnableto the delegateExecutor. In this instance, the sameSecurityContextwill be used for everyRunnablesubmitted to ourDelegatingSecurityContextExecutor. This is nice if we are running background tasks that need to be run by a user with elevated privileges.
At this point you may be asking 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.
@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, then the originalRunnable is executed, and then the SecurityContextHolder is cleared out. In this example, the same user is being used to execute each Thread. What if we wanted to use the user from SecurityContextHolder at the time we invoked executor.execute(Runnable) (i.e. the currently logged in user) to process originalRunnable? This can be done by removing the SecurityContext argument from our DelegatingSecurityContextExecutor constructor. For example:
SimpleAsyncTaskExecutor delegateExecutor = new SimpleAsyncTaskExecutor();
DelegatingSecurityContextExecutor executor =
new DelegatingSecurityContextExecutor(delegateExecutor);
Now anytime executor.execute(Runnable) is executed the SecurityContext is first obtained by the SecurityContextHolder and then that SecurityContext is used to create our DelegatingSecurityContextRunnable. This means that we are executing our Runnable with the same user that was used to invoke the executor.execute(Runnable) code.
Spring Security Concurrency Classes
Refer to the Javadoc for additional integrations with both the Java concurrent APIs and the Spring Task abstractions. They are quite self explanatory once you understand the previous code.
- DelegatingSecurityContextCallable
- DelegatingSecurityContextExecutor
- DelegatingSecurityContextExecutorService
- DelegatingSecurityContextRunnable
- DelegatingSecurityContextScheduledExecutorService
- DelegatingSecurityContextSchedulingTaskExecutor
- DelegatingSecurityContextAsyncTaskExecutor
- DelegatingSecurityContextTaskExecutor
Servlet 3 API Integration
Spring Security has supported Servlet API integration for quite some time. However, it wasn't until 3.2 M1 that it supported the new methods added in Servlet 3. In this section we will discuss each of the methods that Spring Security integrates with. If you want to see this in action, you can import Spring Security into Spring Tool Suite using the Gradle Plugin and run servletapi sample application.
HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)
Spring Security now integrates with HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse). In short, we can use this method to ensure that a user is authenticated. If they are not authenticated, the configured AuthenticationEntryPoint will be used to request the user to authenticate (i.e. redirect to the login page).
HttpServletRequest.login(String,String)
Spring Security now integrates with HttpServletRequest.login(String,String). User's can utilize this method to authenticate a username and password with Spring Security. If authentication fails, a ServletException that wraps the original Spring Security AuthenticationException will be thrown. This means if you allow the ServletException to propagate Spring Security's ExceptionTranslationFilter will handle it for you. Alternatively, you can catch the ServletException and handle it yourself.
HttpServletRequest.logout()
Spring Security now integrates with HttpServletRequest.logout() by invoking the configured LogoutHandler implementations. Typically this means that the SecurityContextHolder will be cleared out, the HttpSession will be invalidated, any "Remember Me" authentication will be cleaned up, etc. However, the configured LogoutHandler implementations will vary depending on your Spring Security configuration. It is important to note that after HttpServletRequest.logout() has been invoked, you are still in charge of writing a response out. Typically this would involve a redirect to the welcome page.
AsyncContext.start(Runnable)
The AsynchContext.start(Runnable) method that ensures your credentials will be propagated to the new Thread. Using Spring Security's newly added concurrency support, Spring Security overrides the AsyncContext.start(Runnable) to ensure that the current SecurityContext is used when processing the Runnable.
Servlet 3 Async Support
Spring Security now supports Servlet 3, Async requests. So how do you use it?
The first step is to ensure you have updated your web.xml to use the 3.0 schema as shown below:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> </web-app>
Next you need to ensure that your springSecurityFilterChain is setup for processing asynchronous requests.
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
That's it! Now Spring Security will ensure that your SecurityContext is propagated on asynchronous requests too.
So what has changed? Internal refactoring within Spring Security will ensure that your SecurityContext is no longer cleared out when a response was committed on another Thread, resulting in a user who appeared to be logged out. Additionally, you can use the Spring Security concurrency support and Spring Security's AsyncContext.start(Runnable) integration to assist you in processing Servlet requests.
Spring MVC Async Integration
More technically speaking, Spring Security integrates with WebAsyncManager. The
SecurityContext that is used to process the Callable is the SecurityContext that exists on the SecurityContextHolder at the time startCallableProcessing is invoked.As Rossen demonstrated in a previous blog post, Spring Web MVC 3.2 has excellent Servlet 3 Async Support. With no additional configuration, Spring Security will automatically setup the SecurityContext to the Thread that executes a Callable returned by your controllers. For example, the following method will automatically have its Callable executed with the SecurityContext that was available when the Callable was created:
@RequestMapping(method=RequestMethod.POST)
public Callable<String> processUpload(final MultipartFile file) {
return new Callable<String>() {
public Object call() throws Exception {
// ...
return "someView";
}
};
}
There is no automatic integration with a DeferredResult that is returned by controllers. This is because DeferredResult is processed by the users and thus there is no way of automatically integrating with it. However, you can still use Concurrency Support to provide transparent integration with Spring Security.
Feedback Please
I hope this gives you a better understanding of the changes that are available in Spring Security 3.2. M1 and gets you excited for the next milestone. As a member of the community I encourage you to try out the new milestone and report any bugs/enhancements in JIRA. This feedback is a simple, yet very important way to give back to the community!
Similar Posts
- Spring MVC 3.2 Preview: Making a Controller Method Asynchronous
- Spring MVC 3.2 Preview: Introducing Servlet 3, Async Support
- Spring MVC 3.2 Preview: Adding Long Polling to an Existing Web Application
- What's New in Spring Security 2?
- Task Scheduling Simplifications in Spring 3.0




Marcin says:
Added on December 20th, 2012 at 4:43 amNice abstraction over delegating security context to background thread. Do you plan to apply similar concept to JMS listeners?
rwinch (blog author) says:
Added on December 20th, 2012 at 9:08 am@Marcin – Thank you for your feedback. At this time there are no thoughts for applying a similar concept to JMS listeners. However, if this is something of interest to you I would encourage you to log a JIRA. Better yet send a pull request
philippe says:
Added on December 21st, 2012 at 4:00 amGood news but are there some samples code that we can clone ? How use the method HttpServletRequest.login(String,String) in an older Spring Security based app ? Thx
rwinch (blog author) says:
Added on December 21st, 2012 at 11:24 am@philippe – The blog post mentions the "servletapi sample application" which is a sample application demonstrating all the Servlet 3 API enhancements found in 3.2 M1. You can clone the Spring Security code base and import it into Spring Tool Suite using the Gradle Plugin.
There is no built in way to use HttpServletRequest.login(String,String) in previous versions of Spring Security (these are new features introduced in 3.2 M1).
rico says:
Added on December 31st, 2012 at 11:18 amIs it possible to provide a Spring Security 3.2 configuration without web.xml now ?
I saw that in AbstractDispatcherServletInitializer available in Spring 3.2, there is a getServletFilters() method which can be overriden to declare filters.
Is it the right place to declare the DelegatingFilterProxy instantiation for full java config ?
Thanks.
rwinch (blog author) says:
Added on December 31st, 2012 at 11:40 am@rico – Using the getServletFilters() would be the location to register the springSecurityFilterChain if you want to secure the DispatcherServlet. However, as of now there is no simple way of using Spring Security with full java config. The next milestone of Spring Security will include Java Configuration for Spring Security. In fact, I am working on some prototypes locally right now. You can follow https://jira.springsource.org/browse/SEC-1953 for details on Spring Security and Java Config.
rico says:
Added on December 31st, 2012 at 2:51 pmThanks @rwinch.
My need for now is to work with a full Servlet 3.0 webapp, so without a web.xml. I am happy if it is the right way to secure the DispatcherServlet.
I can go on with the application context xml file for Spring Security for the moment. No problem.
But i will follow the SEC-1953 improvement, it would be very nice to have a full Java Config for Spring Security.
Thanks again.
Felix says:
Added on January 25th, 2013 at 5:32 pmIs @Async supported by default? If not, how can i make it work?
rwinch (blog author) says:
Added on January 28th, 2013 at 11:55 am@Felix
@Async is supported, but you must configure the Executor that processes @Async to be an instance of DelegatingSecurityContextExecutor. For example, if you were using the task namespace support you might use task:annotation-driven executor="delegatingSecurityContextExecutor" (assuming delegatingSecurityContextExecutor was an instance of DelegatingSecurityContextExecutor).
truetime says:
Added on March 21st, 2013 at 8:23 pmIf I have a list of requirement for web security, how can I provide for you
James Bloom says:
Added on April 2nd, 2013 at 11:34 amIs there a simple working example of using best practices with Spring Security, i.e. on github?
rwinch (blog author) says:
Added on April 9th, 2013 at 8:12 am@James – due to its breadth of coverage, there is not a one size fits all best practice application demonstrating Spring Security. For samples, please refer to the Spring Security sample applications https://github.com/SpringSource/spring-security/tree/master/samples