2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								[[mvc]]
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								= Spring MVC Integration
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Spring Security provides a number of optional integrations with Spring MVC.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								This section covers the integration in further detail.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[[mvc-enablewebmvcsecurity]]
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								== @EnableWebMvcSecurity
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[NOTE]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								As of Spring Security 4.0, `@EnableWebMvcSecurity` is deprecated.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The replacement is `@EnableWebSecurity`, which adds the Spring MVC features, based upon the classpath.
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								To enable Spring Security integration with Spring MVC, add the `@EnableWebSecurity` annotation to your configuration.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[NOTE]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Spring Security provides the configuration by using Spring MVC's https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web.html#mvc-config-customize[`WebMvcConfigurer`].
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								This means that, if you use more advanced options, such as integrating with `WebMvcConfigurationSupport` directly, you need to manually provide the Spring Security configuration.
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[[mvc-requestmatcher]]
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								== MvcRequestMatcher
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Spring Security provides deep integration with how Spring MVC matches on URLs with `MvcRequestMatcher`.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								This is helpful to ensure that your Security rules match the logic used to handle your requests.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								To use `MvcRequestMatcher`, you must place the Spring Security Configuration in the same `ApplicationContext` as your `DispatcherServlet`.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								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.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								For a `web.xml` file, this means that you should place your configuration in the `DispatcherServlet.xml`:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[source,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>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The following `WebSecurityConfiguration` in placed in the  `ApplicationContext` of the `DispatcherServlet`.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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[] { "/" };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class SecurityInitializer : AbstractAnnotationConfigDispatcherServletInitializer() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    override fun getRootConfigClasses(): Array<Class<*>>? {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return null
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    override fun getServletConfigClasses(): Array<Class<*>> {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return arrayOf(
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            RootConfiguration::class.java,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WebMvcConfiguration::class.java
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    override fun getServletMappings(): Array<String> {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return arrayOf("/")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								[NOTE]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								We always recommend that you provide authorization rules by matching on the `HttpServletRequest` and method security.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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, your application is still secured.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								This is known as https://en.wikipedia.org/wiki/Defense_in_depth_(computing)[Defense in Depth]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Consider a controller that is mapped as follows:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/admin")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public String admin() {
							 
						 
					
						
							
								
									
										
										
										
											2021-12-13 16:57:36 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/admin")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								fun admin(): String {
							 
						 
					
						
							
								
									
										
										
										
											2021-12-13 16:57:36 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // ...
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								To restrict access to this controller method to admin users, you can provide authorization rules by matching on the `HttpServletRequest` with the following:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2022-02-08 16:12:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								@Bean
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									http
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										.authorizeHttpRequests((authorize) -> authorize
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											.requestMatchers("/admin").hasRole("ADMIN")
							 
						 
					
						
							
								
									
										
										
										
											2019-07-12 13:58:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										);
							 
						 
					
						
							
								
									
										
										
										
											2022-02-08 16:12:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return http.build();
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2022-02-08 16:12:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								@Bean
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								open fun filterChain(http: HttpSecurity): SecurityFilterChain {
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    http {
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        authorizeHttpRequests {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            authorize("/admin", hasRole("ADMIN"))
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
									
										
										
										
											2022-02-08 16:12:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return http.build()
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The following listing does the same thing in XML:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[source,xml]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<http>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									<intercept-url pattern="/admin" access="hasRole('ADMIN')"/>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								</http>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								With either configuration, the `/admin` URL requires the authenticated user to be an admin user.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								However, depending on our Spring MVC configuration, the `/admin.html` URL also maps to our `admin()` method.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Additionally, depending on our Spring MVC configuration, the `/admin` URL also maps to our `admin()` method.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The problem is that our security rule protects only  `/admin`.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								We could add additional rules for all the permutations of Spring MVC, but this would be quite verbose and tedious.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2022-02-08 16:12:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								@Bean
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector).servletPath("/path");
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									http
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										.authorizeHttpRequests((authorize) -> authorize
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											.requestMatchers(mvcMatcherBuilder.pattern("/admin")).hasRole("ADMIN")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											.requestMatchers(mvcMatcherBuilder.pattern("/user")).hasRole("USER")
							 
						 
					
						
							
								
									
										
										
										
											2019-07-12 13:58:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										);
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return http.build();
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2022-02-08 16:12:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								@Bean
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								open fun filterChain(http: HttpSecurity, introspector: HandlerMappingIntrospector): SecurityFilterChain {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    val mvcMatcherBuilder = MvcRequestMatcher.Builder(introspector)
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    http {
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        authorizeHttpRequests {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            authorize(mvcMatcherBuilder.pattern("/admin"), hasRole("ADMIN"))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            authorize(mvcMatcherBuilder.pattern("/user"), hasRole("USER"))
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
									
										
										
										
											2022-09-21 10:09:35 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return http.build()
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The following XML has the same effect:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[source,xml]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<http request-matcher="mvc">
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									<intercept-url pattern="/admin" access="hasRole('ADMIN')"/>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								</http>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[[mvc-authentication-principal]]
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								== @AuthenticationPrincipal
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Spring Security provides `AuthenticationPrincipalArgumentResolver`, which can automatically resolve the current `Authentication.getPrincipal()` for Spring MVC arguments.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								By using `@EnableWebSecurity`, you automatically have this added to your Spring MVC configuration.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								If you use XML-based configuration, you must add this yourself:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[source,xml]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<mvc:annotation-driven>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										<mvc:argument-resolvers>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										</mvc:argument-resolvers>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								</mvc:annotation-driven>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Once you have properly configured `AuthenticationPrincipalArgumentResolver`, you can entirely decouple from Spring Security in your Spring MVC layer.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Consider a situation where a custom `UserDetailsService` returns an `Object` that implements `UserDetails` and your own `CustomUser` `Object`. The `CustomUser` of the currently authenticated user could be accessed by using the following code:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@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 ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/messages/inbox")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								open fun findMessagesForUser(): ModelAndView {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    val authentication: Authentication = SecurityContextHolder.getContext().authentication
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    val custom: CustomUser? = if (authentication as CustomUser == null) null else authentication.principal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .. find messages for this user and return them ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								As of Spring Security 3.2, we can resolve the argument more directly by adding an annotation:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import org.springframework.security.core.annotation.AuthenticationPrincipal;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/messages/inbox")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public ModelAndView findMessagesForUser(@AuthenticationPrincipal CustomUser customUser) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// .. find messages for this user and return them ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/messages/inbox")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								open fun findMessagesForUser(@AuthenticationPrincipal customUser: CustomUser?): ModelAndView {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .. find messages for this user and return them ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Sometimes, you may need 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 return an `Object` that implements `UserDetails` and provides a method named `getCustomUser` to access `CustomUser`:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public class CustomUserUserDetails extends User {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										public CustomUser getCustomUser() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return customUser;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class CustomUserUserDetails(
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    username: String?,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    password: String?,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    authorities: MutableCollection<out GrantedAuthority>?
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								) : User(username, password, authorities) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    val customUser: CustomUser? = null
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								We could then access the `CustomUser` by 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:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import org.springframework.security.core.annotation.AuthenticationPrincipal;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/messages/inbox")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public ModelAndView findMessagesForUser(@AuthenticationPrincipal(expression = "customUser") CustomUser customUser) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-03 23:51:03 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// .. find messages for this user and return them ...
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import org.springframework.security.core.annotation.AuthenticationPrincipal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/messages/inbox")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								open fun findMessagesForUser(@AuthenticationPrincipal(expression = "customUser") customUser: CustomUser?): ModelAndView {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .. find messages for this user and return them ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								We can also refer to beans in our SpEL expressions.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								For example, we could use the following if we were using JPA to manage our users and if we wanted to modify and save a property on the current user:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import org.springframework.security.core.annotation.AuthenticationPrincipal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@PutMapping("/users/self")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								open fun updateName(
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @AuthenticationPrincipal(expression = "@jpaEntityManager.merge(#this)") attachedCustomUser: CustomUser,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @RequestParam firstName: String?
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								): ModelAndView {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // change the firstName on an attached instance which will be persisted to the database
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    attachedCustomUser.setFirstName(firstName)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								We can further remove our dependency on Spring Security by making `@AuthenticationPrincipal` a meta-annotation on our own annotation.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The next example demonstrates how we could do so on an annotation named `@CurrentUser`.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[NOTE]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								To remove the dependency on Spring Security, it is the consuming application that would create `@CurrentUser`.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								This step is not strictly required but assists in isolating your dependency to Spring Security to a more central location.
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@Target({ElementType.PARAMETER, ElementType.TYPE})
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@Retention(RetentionPolicy.RUNTIME)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@Documented
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@AuthenticationPrincipal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public @interface CurrentUser {}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@Retention(AnnotationRetention.RUNTIME)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@MustBeDocumented
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@AuthenticationPrincipal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								annotation class CurrentUser
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								We have isolated our dependency on Spring Security to a single file.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Now that `@CurrentUser` has been specified, we can use it to signal to resolve our `CustomUser` of the currently authenticated user:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/messages/inbox")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public ModelAndView findMessagesForUser(@CurrentUser CustomUser customUser) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// .. find messages for this user and return them ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping("/messages/inbox")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								open fun findMessagesForUser(@CurrentUser customUser: CustomUser?): ModelAndView {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .. find messages for this user and return them ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[[mvc-async]]
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								== Spring MVC Async Integration
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-19 23:53:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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].
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								With no additional configuration, Spring Security automatically sets up the `SecurityContext` to the `Thread` that invokes a `Callable` returned by your controllers.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								For example, the following method automatically has its `Callable` invoked with the `SecurityContext` that was available when the `Callable` was created:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping(method=RequestMethod.POST)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public Callable<String> processUpload(final MultipartFile file) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								return new Callable<String>() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									public Object call() throws Exception {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return "someView";
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RequestMapping(method = [RequestMethod.POST])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								open fun processUpload(file: MultipartFile?): Callable<String> {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return Callable {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // ...
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "someView"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								.Associating SecurityContext to Callable's
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 14:12:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[NOTE]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								More technically speaking, Spring Security integrates with `WebAsyncManager`.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The `SecurityContext` that is used to process the `Callable` is the `SecurityContext` that exists on the `SecurityContextHolder` when `startCallableProcessing` is invoked.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								====
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								There is no automatic integration with a `DeferredResult` that is returned by controllers.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								This is because `DeferredResult` is processed by the users and, thus, there is no way of automatically integrating with it.
							 
						 
					
						
							
								
									
										
										
										
											2021-09-21 14:53:38 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								However, you can still use xref:features/integrations/concurrency.adoc#concurrency[Concurrency Support] to provide transparent integration with Spring Security.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[[mvc-csrf]]
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								== Spring MVC and CSRF Integration
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Spring Security integrates with Spring MVC to add CSRF protection.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								=== Automatic Token Inclusion
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-02 16:08:37 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Spring Security automatically xref:servlet/exploits/csrf.adoc#csrf-integration-form[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].
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Consider the following JSP:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[source,xml]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<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>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The preceding example output HTMLs that is similar to the following:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[source,xml]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<!-- ... -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<form action="/context/logout" method="post">
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<input type="submit" value="Log out"/>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<input type="hidden" name="_csrf" value="f81d4fae-7dec-11d0-a765-00a0c91e6bf6"/>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								</form>
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								<!-- ... -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								[[mvc-csrf-resolver]]
							 
						 
					
						
							
								
									
										
										
										
											2021-07-30 13:52:15 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								=== Resolving the CsrfToken
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Spring Security provides `CsrfTokenArgumentResolver`, which can automatically resolve the current `CsrfToken` for Spring MVC arguments.
							 
						 
					
						
							
								
									
										
										
										
											2021-12-13 16:57:36 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								By using xref:servlet/configuration/java.adoc#jc-hello-wsca[@EnableWebSecurity], you automatically have this added to your Spring MVC configuration.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								If you use XML-based configuration, you must add this yourself.
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Once `CsrfTokenArgumentResolver` is properly configured, you can expose the `CsrfToken` to your static HTML based application:
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[tabs]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Java::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,java,role="primary"]
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RestController
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public class CsrfController {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									@RequestMapping("/csrf")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									public CsrfToken csrf(CsrfToken token) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return token;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Kotlin::
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								+
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								[source,kotlin,role="secondary"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								@RestController
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class CsrfController {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @RequestMapping("/csrf")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fun csrf(token: CsrfToken): CsrfToken {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return token
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								----
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 21:30:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								======
							 
						 
					
						
							
								
									
										
										
										
											2021-06-16 10:31:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 11:58:02 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								It is important to keep the `CsrfToken` a secret from other domains.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-21 16:01:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								This means that, if you use 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.