NOTE: 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.
NOTE: Spring Security provides the configuration using Spring MVC's https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web.html#mvc-config-customize[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`.
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 https://en.wikipedia.org/wiki/Attack_surface[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 https://en.wikipedia.org/wiki/Defense_in_depth_(computing)[Defence in Depth]
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:
Fortunately, when using the `requestMatchers` DSL method, Spring Security automatically creates a `MvcRequestMatcher` if it detects that Spring MVC is available in the classpath.
Therefore, it will protect the same URLs that Spring MVC will match on by using Spring MVC to match on the URL.
One common requirement when using Spring MVC is to specify the servlet path property, for that you can use the `MvcRequestMatcher.Builder` to create multiple `MvcRequestMatcher` instances that share the same servlet path:
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.
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:
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`.
We could then access the `CustomUser` using a https://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html[SpEL expression] that uses `Authentication.getPrincipal()` as the root object:
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`.
NOTE: 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.
Spring Web MVC 3.2+ has excellent support for https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-async[Asynchronous Request Processing].
With no additional configuration, Spring Security will automatically setup the `SecurityContext` to the `Thread` that invokes a `Callable` returned by your controllers.
For example, the following method will automatically have its `Callable` invoked with the `SecurityContext` that was available when the `Callable` was created:
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 xref:features/integrations/concurrency.adoc#concurrency[Concurrency Support] to provide transparent integration with Spring Security.
Spring Security will automatically xref:servlet/exploits/csrf.adoc#servlet-csrf-include[include the CSRF Token] within forms that use the https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/view.html#view-jsp-formtaglib-formtag[Spring MVC form tag].
By using xref:servlet/configuration/java.adoc#jc-hello-wsca[@EnableWebSecurity] you will automatically have this added to your Spring MVC configuration.
It is important to keep the `CsrfToken` a secret from other domains.
This means if you are using https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS[Cross Origin Sharing (CORS)], you should **NOT** expose the `CsrfToken` to any external domains.