14.1 Servlet API integration

This section describes how Spring Security is integrated with the Servlet API. The servletapi-xml sample application demonstrates the usage of each of these methods.

The HttpServletRequest.getRemoteUser() will return the result of SecurityContextHolder.getContext().getAuthentication().getName() which is typically the current username. This can be useful if you want to display the current username in your application. Additionally, checking if this is null can be used to indicate if a user has authenticated or is anonymous. Knowing if the user is authenticated or not can be useful for determining if certain UI elements should be shown or not (i.e. a log out link should only be displayed if the user is authenticated).

The HttpServletRequest.getUserPrincipal() will return the result of SecurityContextHolder.getContext().getAuthentication() . This means it is an Authentication which is typically an instance of UsernamePasswordAuthenticationToken when using username and password based authentication. This can be useful if you need additional information about your user. For example, you might have created a custom UserDetailsService that returns a custom UserDetails containing a first and last name for your user. You could obtain this information with the following:

Authentication auth = httpServletRequest.getUserPrincipal();
// assume integrated custom UserDetails called MyCustomUserDetails
// by default, typically instance of UserDetails
MyCustomUserDetails userDetails = (MyCustomUserDetails) auth.getPrincipal();
String firstName = userDetails.getFirstName();
String lastName = userDetails.getLastName();

It should be noted that it is typically bad practice to perform so much logic throughout your application. Instead, one should centralize it to reduce any coupling of Spring Security and the Servlet API’s.

The HttpServletRequest.isUserInRole(String) will determine if SecurityContextHolder.getContext().getAuthentication().getAuthorities() contains a GrantedAuthority with the role passed into isUserInRole(String) . Typically users should not pass in the "ROLE_" prefix into this method since it is added automatically. For example, if you want to determine if the current user has the authority "ROLE_ADMIN", you could use the following:

boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");

This might be useful to determine if certain UI components should be displayed. For example, you might display admin links only if the current user is an admin.

The following section describes the Servlet 3 methods that Spring Security integrates with.

The HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) method can be used 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).

The HttpServletRequest.login(String,String) method can be used to authenticate the user with the current AuthenticationManager . For example, the following would attempt to authenticate with the username "user" and password "password":

try {
httpServletRequest.login("user","password");
} catch(ServletException e) {
// fail to authenticate

It is not necessary to catch the ServletException if you want Spring Security to process the failed authentication attempt.

The HttpServletRequest.logout() method can be used to log the current user out.

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.

The AsynchContext.start(Runnable) method that ensures your credentials will be propagated to the new Thread. Using Spring Security’s concurrency support, Spring Security overrides the AsyncContext.start(Runnable) to ensure that the current SecurityContext is used when processing the Runnable. For example, the following would output the current user’s Authentication:

final AsyncContext async = httpServletRequest.startAsync();
async.start(new Runnable() {
    public void run() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        try {
            final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse();
            asyncResponse.setStatus(HttpServletResponse.SC_OK);
            asyncResponse.getWriter().write(String.valueOf(authentication));
            async.complete();
        } catch(Exception e) {
            throw new RuntimeException(e);

If you are using Java Based configuration, you are ready to go. If you are using XML configuration, there are a few updates that are necessary. The first step is to ensure you have updated your web.xml to use at least 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 https://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 how does it work? If you are not really interested, feel free to skip the remainder of this section, otherwise read on. Most of this is built into the Servlet specification, but there is a little bit of tweaking that Spring Security does to ensure things work with asynchronous requests properly. Prior to Spring Security 3.2, the SecurityContext from the SecurityContextHolder was automatically saved as soon as the HttpServletResponse was committed. This can cause issues in an Async environment. For example, consider the following:

httpServletRequest.startAsync();
new Thread("AsyncThread") {
    @Override
    public void run() {
        try {
            // Do work
            TimeUnit.SECONDS.sleep(1);
            // Write to and commit the httpServletResponse
            httpServletResponse.getOutputStream().flush();
        } catch (Exception e) {
            e.printStackTrace();
}.start();

The issue is that this Thread is not known to Spring Security, so the SecurityContext is not propagated to it. This means when we commit the HttpServletResponse there is no SecuriytContext. When Spring Security automatically saved the SecurityContext on committing the HttpServletResponse it would lose our logged in user.

Since version 3.2, Spring Security is smart enough to no longer automatically save the SecurityContext on commiting the HttpServletResponse as soon as HttpServletRequest.startAsync() is invoked.

The following section describes the Servlet 3.1 methods that Spring Security integrates with.

The HttpServletRequest.changeSessionId() is the default method for protecting against Session Fixation attacks in Servlet 3.1 and higher.

Spring Security provides Spring Data integration that allows referring to the current user within your queries. It is not only useful but necessary to include the user in the queries to support paged results since filtering the results afterwards would not scale.

14.2.1 Spring Data & Spring Security Configuration

To use this support, add org.springframework.security:spring-security-data dependency and provide a bean of type SecurityEvaluationContextExtension. In Java Configuration, this would look like:

@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
    return new SecurityEvaluationContextExtension();

In XML Configuration, this would look like:

<bean class="org.springframework.security.data.repository.query.SecurityEvaluationContextExtension"/>

Now Spring Security can be used within your queries. For example:

@Repository
public interface MessageRepository extends PagingAndSortingRepository<Message,Long> {
    @Query("select m from Message m where m.to.id = ?#{ principal?.id }")
    Page<Message> findInbox(Pageable pageable);

This checks to see if the Authentication.getPrincipal().getId() is equal to the recipient of the Message. Note that this example assumes you have customized the principal to be an Object that has an id property. By exposing the SecurityEvaluationContextExtension bean, all of the Common Security Expressions are available within the Query.

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 for users. 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 integration with the section called “AsyncContext.start(Runnable)” and Section 14.6.4, “Spring MVC Async Integration”.

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 the section called “<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 Runnable that will be invoking our secured service. Notice that it is not aware of Spring Security Obtains the SecurityContext that we wish to use from the SecurityContextHolder and initializes the DelegatingSecurityContextRunnable Use the DelegatingSecurityContextRunnable to create a Thread Start the Thread we 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.

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 SecurityContext to be used for our DelegatingSecurityContextExecutor. Note that in this example we simply create the SecurityContext by hand. However, it does not matter where or how we get the SecurityContext (i.e. we could obtain it from the SecurityContextHolder if we wanted). Creates a delegateExecutor that is in charge of executing submitted Runnables 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 instance, the same SecurityContext will be used for every Runnable submitted to our DelegatingSecurityContextExecutor. 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.

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 DelegatingSecurityContextTaskScheduler

Spring Security has added Jackson Support for persisting Spring Security related classes. This can improve the performance of serializing Spring Security related classes when working with distributed sessions (i.e. session replication, Spring Session, etc).

To use it, register the SecurityJackson2Modules.getModules(ClassLoader) as Jackson Modules.

ObjectMapper mapper = new ObjectMapper();
ClassLoader loader = getClass().getClassLoader();
List<Module> modules = SecurityJackson2Modules.getModules(loader);
mapper.registerModules(modules);
// ... use ObjectMapper as normally ...
SecurityContext context = new SecurityContextImpl();
// ...
String json = mapper.writeValueAsString(context);

Spring Security supports localization of exception messages that end users are likely to see. If your application is designed for English-speaking users, you don’t need to do anything as by default all Security messages are in English. If you need to support other locales, everything you need to know is contained in this section.

All exception messages can be localized, including messages related to authentication failures and access being denied (authorization failures). Exceptions and logging messages that are focused on developers or system deployers (including incorrect attributes, interface contract violations, using incorrect constructors, startup time validation, debug-level logging) are not localized and instead are hard-coded in English within Spring Security’s code.

Shipping in the spring-security-core-xx.jar you will find an org.springframework.security package that in turn contains a messages.properties file, as well as localized versions for some common languages. This should be referred to by your ApplicationContext, as Spring Security classes implement Spring’s MessageSourceAware interface and expect the message resolver to be dependency injected at application context startup time. Usually all you need to do is register a bean inside your application context to refer to the messages. An example is shown below:

<bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:org/springframework/security/messages"/>
</bean>

The messages.properties is named in accordance with standard resource bundles and represents the default language supported by Spring Security messages. This default file is in English.

If you wish to customize the messages.properties file, or support other languages, you should copy the file, rename it accordingly, and register it inside the above bean definition. There are not a large number of message keys inside this file, so localization should not be considered a major initiative. If you do perform localization of this file, please consider sharing your work with the community by logging a JIRA task and attaching your appropriately-named localized version of messages.properties.

Spring Security relies on Spring’s localization support in order to actually lookup the appropriate message. In order for this to work, you have to make sure that the locale from the incoming request is stored in Spring’s org.springframework.context.i18n.LocaleContextHolder. Spring MVC’s DispatcherServlet does this for your application automatically, but since Spring Security’s filters are invoked before this, the LocaleContextHolder needs to be set up to contain the correct Locale before the filters are called. You can either do this in a filter yourself (which must come before the Spring Security filters in web.xml) or you can use Spring’s RequestContextFilter. Please refer to the Spring Framework documentation for further details on using localization with Spring.

The "contacts" sample application is set up to use localized messages.

14.6 Spring MVC Integration

Spring Security provides a number of optional integrations with Spring MVC. This section covers the integration in further detail.

As of Spring Security 4.0, @EnableWebMvcSecurity is deprecated. The replacement is @EnableWebSecurity which will determine adding the Spring MVC features based upon the classpath.

To enable Spring Security integration with Spring MVC add the @EnableWebSecurity annotation to your configuration.

Spring Security provides the configuration using Spring MVC’s WebMvcConfigurer. This means that if you are using more advanced options, like integrating with WebMvcConfigurationSupport directly, then you will need to manually provide the Spring Security configuration.

Spring Security provides deep integration with how Spring MVC matches on URLs with MvcRequestMatcher. This is helpful to ensure your Security rules match the logic used to handle your requests.

In order to use MvcRequestMatcher you must place the Spring Security Configuration in the same ApplicationContext as your DispatcherServlet. This is necessary because Spring Security’s MvcRequestMatcher expects a HandlerMappingIntrospector bean with the name of mvcHandlerMappingIntrospector to be registered by your Spring MVC configuration that is used to perform the matching.

For a web.xml this means that you should place your configuration in the DispatcherServlet.xml.

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- All Spring Configuration (both MVC and Security) are in /WEB-INF/spring/ -->
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring/*.xml</param-value>
</context-param>
<servlet>
  <servlet-name>spring</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <!-- Load from the ContextLoaderListener -->
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value></param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>spring</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

Below WebSecurityConfiguration in placed in the DispatcherServlets ApplicationContext.

public class SecurityInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {
  @Override
  protected Class<?>[] getRootConfigClasses() {
    return null;
  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class[] { RootConfiguration.class,
        WebMvcConfiguration.class };
  @Override
  protected String[] getServletMappings() {
    return new String[] { "/" };

It is always recommended to provide authorization rules by matching on the HttpServletRequest and method security.

Providing authorization rules by matching on HttpServletRequest is good because it happens very early in the code path and helps reduce the attack surface. Method security ensures that if someone has bypassed the web authorization rules, that your application is still secured. This is what is known as Defence in Depth

Consider a controller that is mapped as follows:

@RequestMapping("/admin")
public String admin() {

If we wanted to restrict access to this controller method to admin users, a developer can provide authorization rules by matching on the HttpServletRequest with the following:

protected configure(HttpSecurity http) throws Exception {
        .authorizeRequests(authorizeRequests ->
            authorizeRequests
                .antMatchers("/admin").hasRole("ADMIN")

or in XML

<intercept-url pattern="/admin" access="hasRole('ADMIN')"/> </http>

With either configuration, the URL /admin will require the authenticated user to be an admin user. However, depending on our Spring MVC configuration, the URL /admin.html will also map to our admin() method. Additionally, depending on our Spring MVC configuration, the URL /admin/ will also map to our admin() method.

The problem is that our security rule is only protecting /admin. We could add additional rules for all the permutations of Spring MVC, but this would be quite verbose and tedious.

Instead, we can leverage Spring Security’s MvcRequestMatcher. The following configuration will protect the same URLs that Spring MVC will match on by using Spring MVC to match on the URL.

protected configure(HttpSecurity http) throws Exception {
        .authorizeRequests(authorizeRequests ->
            authorizeRequests
                .mvcMatchers("/admin").hasRole("ADMIN")

or in XML

<http request-matcher="mvc">
    <intercept-url pattern="/admin" access="hasRole('ADMIN')"/>
</http>

Spring Security provides AuthenticationPrincipalArgumentResolver which can automatically resolve the current Authentication.getPrincipal() for Spring MVC arguments. By using @EnableWebSecurity you will automatically have this added to your Spring MVC configuration. If you use XML based configuration, you must add this yourself. For example:

<mvc:annotation-driven>
        <mvc:argument-resolvers>
                <bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
        </mvc:argument-resolvers>
</mvc:annotation-driven>

Once AuthenticationPrincipalArgumentResolver is properly configured, you can be entirely decoupled from Spring Security in your Spring MVC layer.

Consider a situation where a custom UserDetailsService that returns an Object that implements UserDetails and your own CustomUser Object. The CustomUser of the currently authenticated user could be accessed using the following code:

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser() {
    Authentication authentication =
    SecurityContextHolder.getContext().getAuthentication();
    CustomUser custom = (CustomUser) authentication == null ? null : authentication.getPrincipal();
    // .. find messages for this user and return them ...

As of Spring Security 3.2 we can resolve the argument more directly by adding an annotation. For example:

import org.springframework.security.core.annotation.AuthenticationPrincipal;
// ...
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal CustomUser customUser) {
    // .. find messages for this user and return them ...

Sometimes it may be necessary to transform the principal in some way. For example, if CustomUser needed to be final it could not be extended. In this situation the UserDetailsService might returns an Object that implements UserDetails and provides a method named getCustomUser to access CustomUser. For example, it might look like:

public class CustomUserUserDetails extends User {
        // ...
        public CustomUser getCustomUser() {
                return customUser;

We could then access the CustomUser using a SpEL expression that uses Authentication.getPrincipal() as the root object:

import org.springframework.security.core.annotation.AuthenticationPrincipal;
// ...
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal(expression = "customUser") CustomUser customUser) {
    // .. find messags for this user and return them ...

We can also refer to Beans in our SpEL expressions. For example, the following could be used if we were using JPA to manage our Users and we wanted to modify and save a property on the current user.

import org.springframework.security.core.annotation.AuthenticationPrincipal;
// ...
@PutMapping("/users/self")
public ModelAndView updateName(@AuthenticationPrincipal(expression = "@jpaEntityManager.merge(#this)") CustomUser attachedCustomUser,
        @RequestParam String firstName) {
    // change the firstName on an attached instance which will be persisted to the database
    attachedCustomUser.setFirstName(firstName);
    // ...

We can further remove our dependency on Spring Security by making @AuthenticationPrincipal a meta annotation on our own annotation. Below we demonstrate how we could do this on an annotation named @CurrentUser.

It is important to realize that in order to remove the dependency on Spring Security, it is the consuming application that would create @CurrentUser. This step is not strictly required, but assists in isolating your dependency to Spring Security to a more central location.

@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {}

Now that @CurrentUser has been specified, we can use it to signal to resolve our CustomUser of the currently authenticated user. We have also isolated our dependency on Spring Security to a single file.

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@CurrentUser CustomUser customUser) {
    // .. find messages for this user and return them ...

14.6.4 Spring MVC Async Integration

Spring Web MVC 3.2+ has excellent support for Asynchronous Request Processing. 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";
[Note]Associating SecurityContext to Callable’s

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.

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.

Spring Security will automatically include the CSRF Token within forms that use the Spring MVC form tag. For example, the following JSP:

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:form="http://www.springframework.org/tags/form" version="2.0">
    <jsp:directive.page language="java" contentType="text/html" />
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <!-- ... -->
    <c:url var="logoutUrl" value="/logout"/>
    <form:form action="${logoutUrl}"
        method="post">
    <input type="submit"
        value="Log out" />
    <input type="hidden"
        name="${_csrf.parameterName}"
        value="${_csrf.token}"/>
    </form:form>
    <!-- ... -->
</html>
</jsp:root>

Will output HTML that is similar to the following:

<!-- ... -->
<form action="/context/logout" method="post">
<input type="submit" value="Log out"/>
<input type="hidden" name="_csrf" value="f81d4fae-7dec-11d0-a765-00a0c91e6bf6"/>
</form>
<!-- ... -->

Spring Security provides CsrfTokenArgumentResolver which can automatically resolve the current CsrfToken for Spring MVC arguments. By using @EnableWebSecurity you will automatically have this added to your Spring MVC configuration. If you use XML based configuraiton, you must add this yourself.

Once CsrfTokenArgumentResolver is properly configured, you can expose the CsrfToken to your static HTML based application.

@RestController
public class CsrfController {
    @RequestMapping("/csrf")
    public CsrfToken csrf(CsrfToken token) {
        return token;

It is important to keep the CsrfToken a secret from other domains. This means if you are using Cross Origin Sharing (CORS), you should NOT expose the CsrfToken to any external domains.

Spring Security 4 added support for securing Spring’s WebSocket support. This section describes how to use Spring Security’s WebSocket support.

You can find a complete working sample of WebSocket security at https://github.com/spring-projects/spring-session/tree/master/samples/boot/websocket.