|  | @@ -0,0 +1,580 @@
 | 
	
		
			
				|  |  | +[[test]]
 | 
	
		
			
				|  |  | += Testing
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-method]]
 | 
	
		
			
				|  |  | +== Testing Method Security
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +This section demonstrates how to  use Spring Security's Test support to test method based security.
 | 
	
		
			
				|  |  | +We first introduce a `MessageService` that requires the user to be authenticated in order to access it.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +public class HelloMessageService implements MessageService {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	@PreAuthorize("authenticated")
 | 
	
		
			
				|  |  | +	public String getMessage() {
 | 
	
		
			
				|  |  | +		Authentication authentication = SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | +                                                             .getAuthentication();
 | 
	
		
			
				|  |  | +		return "Hello " + authentication;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +The result of `getMessage` is a String saying "Hello" to the current Spring Security `Authentication`.
 | 
	
		
			
				|  |  | +An example of the output is displayed below.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,text]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +Hello org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ca25360: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-method-setup]]
 | 
	
		
			
				|  |  | +=== Security Test Setup
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Before we can use Spring Security Test support, we must perform some setup. An example can be seen below:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@RunWith(SpringJUnit4ClassRunner.class) // <1>
 | 
	
		
			
				|  |  | +@ContextConfiguration // <2>
 | 
	
		
			
				|  |  | +public class WithMockUserTests {
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +This is a basic example of how to setup Spring Security Test. The highlights are:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<1> `@RunWith` instructs the spring-test module that it should create an ApplicationContext This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard[Spring Reference]
 | 
	
		
			
				|  |  | +<2> `@ContextConfiguration` instructs the spring-test the configuration to use to create the `ApplicationContext`. Since no configuration is specified, the default configuration locations will be tried. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#testcontext-ctx-management[Spring Reference]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +NOTE: Spring Security hooks into Spring Test support using the  `WithSecurityContextTestExcecutionListener` which will ensure our tests are ran with the correct user.
 | 
	
		
			
				|  |  | +It does this by populating the `SecurityContextHolder` prior to running our tests.
 | 
	
		
			
				|  |  | +After the test is done, it will clear out the `SecurityContextHolder`.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Remember we added the `@PreAuthorize` annotation to our `HelloMessageService` and so it requires an authenticated user to invoke it.
 | 
	
		
			
				|  |  | +If we ran the following test, we would expect the following test will pass:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test(expected = AuthenticationCredentialsNotFoundException.class)
 | 
	
		
			
				|  |  | +public void getMessageUnauthenticated() {
 | 
	
		
			
				|  |  | +    messageService.getMessage();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-method-withmockuser]]
 | 
	
		
			
				|  |  | +=== @WithMockUser
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +The question is "How could we most easily run the test as a specific user?"
 | 
	
		
			
				|  |  | +The answer is to use `@WithMockUser`.
 | 
	
		
			
				|  |  | +The following test will be ran as a user with the username "user", the password "password", and the roles "ROLE_USER".
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test
 | 
	
		
			
				|  |  | +@WithMockUser
 | 
	
		
			
				|  |  | +public void getMessageWithMockUser() {
 | 
	
		
			
				|  |  | +  String message = messageService.getMessage();
 | 
	
		
			
				|  |  | +  ...
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Specifically the following is true:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +* The user with the username "user" does not have to exist since we are mocking the user
 | 
	
		
			
				|  |  | +* The `Authentication` that is populated in the `SecurityContext` is of type `UsernamePasswordAuthenticationToken`
 | 
	
		
			
				|  |  | +* The principal on the `Authentication` is Spring Security's `User` object
 | 
	
		
			
				|  |  | +* The `User` will have the username of "user", the password "password", and a single `GrantedAuthority` named "ROLE_USER" is used.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Our example is nice because we are able to leverage a lot of defaults.
 | 
	
		
			
				|  |  | +What if we wanted to run the test with a different username?
 | 
	
		
			
				|  |  | +The following test would run with the username "customUser". Again, the user does not need to actually exist.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test
 | 
	
		
			
				|  |  | +@WithMockUser("customUsername")
 | 
	
		
			
				|  |  | +public void getMessageWithMockUserCustomUsername() {
 | 
	
		
			
				|  |  | +	String message = messageService.getMessage();
 | 
	
		
			
				|  |  | +  ...
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We can also easily customize the roles.
 | 
	
		
			
				|  |  | +For example, this test will be invoked with the username "admin" and the roles "ROLE_USER" and "ROLE_ADMIN".
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test
 | 
	
		
			
				|  |  | +@WithMockUser(username="admin",roles={"USER","ADMIN"})
 | 
	
		
			
				|  |  | +public void getMessageWithMockUserCustomUser() {
 | 
	
		
			
				|  |  | +	String message = messageService.getMessage();
 | 
	
		
			
				|  |  | +	...
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Of course it can be a bit tedious placing the annotation on every test method.
 | 
	
		
			
				|  |  | +Instead, we can place the annotation at the class level and every test will use the specified user.
 | 
	
		
			
				|  |  | +For example, the following would run every test with a user with the username "admin", the password "password", and the roles "ROLE_USER" and "ROLE_ADMIN".
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@RunWith(SpringJUnit4ClassRunner.class)
 | 
	
		
			
				|  |  | +@ContextConfiguration
 | 
	
		
			
				|  |  | +@WithMockUser(username="admin",roles={"USER","ADMIN"})
 | 
	
		
			
				|  |  | +public class WithMockUserTests {
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-method-withuserdetails]]
 | 
	
		
			
				|  |  | +=== @WithUserDetails
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +While `@WithMockUser` is a very convenient way to get started, it may not work in all instances.
 | 
	
		
			
				|  |  | +For example, it is common for applications to expect that the `Authentication` principal be of a specific type.
 | 
	
		
			
				|  |  | +This is done so that the application can refer to the principal as the custom type and reduce coupling on Spring Security.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +The custom principal is often times returned by a custom `UserDetailsService` that returns an object that implements both `UserDetails` and the custom type.
 | 
	
		
			
				|  |  | +For situations like this, it is useful to create the test user using the custom `UserDetailsService`.
 | 
	
		
			
				|  |  | +That is exactly what `@WithUserDetails` does.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Assuming we have a `UserDetailsService` exposed as a bean, the following test will be invoked with an `Authentication` of type `UsernamePasswordAuthenticationToken` and a principal that is returned from the `UserDetailsService` with the username of "user".
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test
 | 
	
		
			
				|  |  | +@WithUserDetails
 | 
	
		
			
				|  |  | +public void getMessageWithUserDetails() {
 | 
	
		
			
				|  |  | +	String message = messageService.getMessage();
 | 
	
		
			
				|  |  | +	...
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We can also customize the username used to lookup the user from our `UserDetailsService`.
 | 
	
		
			
				|  |  | +For example, this test would be executed with a principal that is returned from the `UserDetailsService` with the username of "customUsername".
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test
 | 
	
		
			
				|  |  | +@WithUserDetails("customUsername")
 | 
	
		
			
				|  |  | +public void getMessageWithUserDetailsCustomUsername() {
 | 
	
		
			
				|  |  | +	String message = messageService.getMessage();
 | 
	
		
			
				|  |  | +	...
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Like `@WithMockUser` we can also place our annotation at the class level so that every test uses the same user.
 | 
	
		
			
				|  |  | +However unlike `@WithMockUser`, `@WithUserDetails` requires the user to exist.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-method-withsecuritycontext]]
 | 
	
		
			
				|  |  | +=== @WithSecurityContext
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We have seen that `@WithMockUser` is an excellent choice if we are not using a custom `Authentication` principal.
 | 
	
		
			
				|  |  | +Next we discovered that `@WithUserDetails` would allow us to use a custom `UserDetailsService` to create our `Authentication` principal but required the user to exist.
 | 
	
		
			
				|  |  | +We will now see an option that allows the most flexibility.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We can create our own annotation that uses the `@WithSecurityContext` to create any `SecurityContext` we want.
 | 
	
		
			
				|  |  | +For example, we might create an annotation named `@WithMockCustomUser` as shown below:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
 | 
	
		
			
				|  |  | +public @interface WithMockCustomUser {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	String username() default "rob";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	String name() default "Rob Winch";
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +You can see that `@WithMockCustomUser` is annotated with the `@WithSecurityContext` annotation.
 | 
	
		
			
				|  |  | +This is what signals to Spring Security Test support that we intend to create a `SecurityContext` for the test.
 | 
	
		
			
				|  |  | +The `@WithSecurityContext` annotation requires we specify a `SecurityContextFactory` that will create a new `SecurityContext` given our `@WithMockCustomUser` annotation.
 | 
	
		
			
				|  |  | +You can find our `WithMockCustomUserSecurityContextFactory` implementation below:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +public class WithMockCustomUserSecurityContextFactory
 | 
	
		
			
				|  |  | +      implements WithSecurityContextFactory<WithMockCustomUser> {
 | 
	
		
			
				|  |  | +	@Override
 | 
	
		
			
				|  |  | +	public SecurityContext createSecurityContext(WithMockCustomUser customUser) {
 | 
	
		
			
				|  |  | +		SecurityContext context = SecurityContextHolder.createEmptyContext();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		CustomUserDetails principal =
 | 
	
		
			
				|  |  | +			new CustomUserDetails(customUser.name(), customUser.username());
 | 
	
		
			
				|  |  | +		Authentication auth =
 | 
	
		
			
				|  |  | +			new UsernamePasswordAuthenticationToken(principal, "password", principal.getAuthorities());
 | 
	
		
			
				|  |  | +		context.setAuthentication(auth);
 | 
	
		
			
				|  |  | +		return context;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We can now annotate a test class or a test method with our new annotation and Spring Security's `WithSecurityContextTestExcecutionListener` will ensure that our `SecurityContext` is populated appropriately.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +When creating your own `WithSecurityContextFactory` implementations, it is nice to know that they can be annotated with standard Spring annotations.
 | 
	
		
			
				|  |  | +For example, the `WithUserDetailsSecurityContextFactory` uses the `@Autowired` annotation to acquire the `UserDetailsService`:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +final class WithUserDetailsSecurityContextFactory
 | 
	
		
			
				|  |  | +	  implements WithSecurityContextFactory<WithUserDetails> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private UserDetailsService userDetailsService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    public WithUserDetailsSecurityContextFactory(UserDetailsService userDetailsService) {
 | 
	
		
			
				|  |  | +        this.userDetailsService = userDetailsService;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public SecurityContext createSecurityContext(WithUserDetails withUser) {
 | 
	
		
			
				|  |  | +        String username = withUser.value();
 | 
	
		
			
				|  |  | +        Assert.hasLength(username, "value() must be non empty String");
 | 
	
		
			
				|  |  | +        UserDetails principal = userDetailsService.loadUserByUsername(username);
 | 
	
		
			
				|  |  | +        Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
 | 
	
		
			
				|  |  | +        SecurityContext context = SecurityContextHolder.createEmptyContext();
 | 
	
		
			
				|  |  | +        context.setAuthentication(authentication);
 | 
	
		
			
				|  |  | +        return context;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-mockmvc]]
 | 
	
		
			
				|  |  | +== Spring MVC Test Integration
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Spring Security provides comprehensive integration with http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework[Spring MVC Test]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-mockmvc-setup]]
 | 
	
		
			
				|  |  | +=== Setting Up MockMvc and Spring Security
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +In order to use Spring Security with Spring MVC Test it is necessary to add the Spring Security `FilterChainProxy` as a `Filter`.
 | 
	
		
			
				|  |  | +It is also necessary to add Spring Security's `TestSecurityContextHolderPostProcessor` to support <<Running as a User in Spring MVC Test with Annotations,Running as a User in Spring MVC Test with Annotations>>.
 | 
	
		
			
				|  |  | +This can be done using Spring Security's `SecurityMockMvcConfigurers.springSecurity()`.
 | 
	
		
			
				|  |  | +For example:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +NOTE: Spring Security's testing support requires spring-test-4.1.3.RELEASE or greater.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@RunWith(SpringJUnit4ClassRunner.class)
 | 
	
		
			
				|  |  | +@ContextConfiguration
 | 
	
		
			
				|  |  | +@WebAppConfiguration
 | 
	
		
			
				|  |  | +public class CsrfShowcaseTests {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private WebApplicationContext context;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private MockMvc mvc;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Before
 | 
	
		
			
				|  |  | +    public void setup() {
 | 
	
		
			
				|  |  | +        mvc = MockMvcBuilders
 | 
	
		
			
				|  |  | +                .webAppContextSetup(context)
 | 
	
		
			
				|  |  | +                .apply(springSecurity()) // <1>
 | 
	
		
			
				|  |  | +                .build();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  ...
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<1> `SecurityMockMvcConfigurers.springSecurity()` will perform all of the initial setup we need to integrate Spring Security with Spring MVC Test
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-mockmvc-smmrpp]]
 | 
	
		
			
				|  |  | +=== SecurityMockMvcRequestPostProcessors
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Spring MVC Test provides a convenient interface called a `RequestPostProcessor` that can be used to modify a request.
 | 
	
		
			
				|  |  | +Spring Security provides a number of `RequestPostProcessor` implementations that make testing easier.
 | 
	
		
			
				|  |  | +In order to use Spring Security's `RequestPostProcessor` implementations ensure the following static import is used:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-mockmvc-csrf]]
 | 
	
		
			
				|  |  | +==== Testing with CSRF Protection
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +When testing any non safe HTTP methods and using Spring Security's CSRF protection, you must be sure to include a valid CSRF Token in the request.
 | 
	
		
			
				|  |  | +To specify a valid CSRF token as a request parameter using the following:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(post("/").with(csrf()))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +If you like you can include CSRF token in the header instead:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(post("/").with(csrf().asHeader()))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +You can also test providing an invalid CSRF token using the following:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(post("/").with(csrf().useInvalidToken()))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-mockmvc-securitycontextholder]]
 | 
	
		
			
				|  |  | +==== Running a Test as a User in Spring MVC Test
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +It is often desirable to run tests as a specific user.
 | 
	
		
			
				|  |  | +There are two simple ways of populating the user:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +* <<Running as a User in Spring MVC Test with RequestPostProcessor,Running as a User in Spring MVC Test with RequestPostProcessor>>
 | 
	
		
			
				|  |  | +* <<Running as a User in Spring MVC Test with Annotations,Running as a User in Spring MVC Test with Annotations>>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[[test-mockmvc-securitycontextholder-rpp]]
 | 
	
		
			
				|  |  | +==== Running as a User in Spring MVC Test with RequestPostProcessor
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +There are a number of options available to populate a test user.
 | 
	
		
			
				|  |  | +For example, the following will run as a user (which does not need to exist) with the username "user", the password "password", and the role "ROLE_USER":
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(get("/").with(user("user")))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +You can easily make customizations.
 | 
	
		
			
				|  |  | +For example, the following will run as a user (which does not need to exist) with the username "admin", the password "pass", and the roles "ROLE_USER" and "ROLE_ADMIN".
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +If you have a custom `UserDetails` that you would like to use, you can easily specify that as well.
 | 
	
		
			
				|  |  | +For example, the following will use the specified `UserDetails` (which does not need to exist) to run with a `UsernamePasswordAuthenticationToken` that has a principal of the specified `UserDetails`:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(get("/").with(user(userDetails)))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +If you want a custom `Authentication` (which does not need to exist) you can do so using the following:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(get("/").with(authentication(authentication)))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +You can even customize the `SecurityContext` using the following:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(get("/").with(securityContext(securityContext)))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We can also ensure to run as a specific user for every request by using `MockMvcBuilders`'s default request.
 | 
	
		
			
				|  |  | +For example, the following will run as a user (which does not need to exist) with the username "admin", the password "password", and the role "ROLE_ADMIN":
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc = MockMvcBuilders
 | 
	
		
			
				|  |  | +        .webAppContextSetup(context)
 | 
	
		
			
				|  |  | +        .defaultRequest(get("/").with(user("user").roles("ADMIN")))
 | 
	
		
			
				|  |  | +        .apply(springSecurity())
 | 
	
		
			
				|  |  | +        .build();
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +If you find you are using the same user in many of your tests, it is recommended to move the user to a method.
 | 
	
		
			
				|  |  | +For example, you can specify the following in your own class named `CustomSecurityMockMvcRequestPostProcessors`:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +public static RequestPostProcessor rob() {
 | 
	
		
			
				|  |  | +	return user("rob").roles("ADMIN");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Now you can perform a static import on `SecurityMockMvcRequestPostProcessors` and use that within your tests:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +import static sample.CustomSecurityMockMvcRequestPostProcessors.*;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +...
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(get("/").with(rob()))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +===== Running as a User in Spring MVC Test with Annotations
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +As an alternative to using a `RequestPostProcessor` to create your user, you can use annotations described in <<Testing Method Security>>.
 | 
	
		
			
				|  |  | +For example, the following will run the test with the user with username "user", password "password", and role "ROLE_USER":
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test
 | 
	
		
			
				|  |  | +@WithMockUser
 | 
	
		
			
				|  |  | +public void requestProtectedUrlWithUser() throws Exception {
 | 
	
		
			
				|  |  | +  mvc
 | 
	
		
			
				|  |  | +      .perform(get("/"))
 | 
	
		
			
				|  |  | +      ...
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Alternatively, the following will run the test with the user with username "user", password "password", and role "ROLE_ADMIN":
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +@Test
 | 
	
		
			
				|  |  | +@WithMockUser(roles="ADMIN")
 | 
	
		
			
				|  |  | +public void requestProtectedUrlWithUser() throws Exception {
 | 
	
		
			
				|  |  | +  mvc
 | 
	
		
			
				|  |  | +      .perform(get("/"))
 | 
	
		
			
				|  |  | +      ...
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +==== Testing HTTP Basic Authentication
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +While it has always been possible to authenticate with HTTP Basic, it was a bit tedious to remember the header name, format, and encode the values.
 | 
	
		
			
				|  |  | +Now this can be done using Spring Security's `httpBasic` `RequestPostProcessor`.
 | 
	
		
			
				|  |  | +For example, the snippet below:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(get("/").with(httpBasic("user","password")))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +will attempt to use HTTP Basic to authenticate a user with the username "user" and the password "password" by ensuring the following header is populated on the HTTP Request:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,text]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +Authorization: Basic dXNlcjpwYXNzd29yZA==
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +=== SecurityMockMvcRequestBuilders
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Spring MVC Test also provides a `RequestBuilder` interface that can be used to create the `MockHttpServletRequest` used in your test.
 | 
	
		
			
				|  |  | +Spring Security provides a few `RequestBuilder` implementations that can be used to make testing easier.
 | 
	
		
			
				|  |  | +In order to use Spring Security's `RequestBuilder` implementations ensure the following static import is used:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +==== Testing Form Based Authentication
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +You can easily create a request to test a form based authentication using Spring Security's testing support.
 | 
	
		
			
				|  |  | +For example, the following will submit a POST to "/login" with the username "user", the password "password", and a valid CSRF token:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin())
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +It is easy to customize the request.
 | 
	
		
			
				|  |  | +For example, the following will submit a POST to "/auth" with the username "admin", the password "pass", and a valid CSRF token:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin("/auth").user("admin").password("pass"))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We can also customize the parameters names that the username and password are included on.
 | 
	
		
			
				|  |  | +For example, this is the above request modified to include the username on the HTTP parameter "u" and the password on the HTTP parameter "p".
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin("/auth").user("a","admin").password("p","pass"))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +==== Testing Logout
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +While fairly trivial using standard Spring MVC Test, you can use Spring Security's testing support to make testing log out easier.
 | 
	
		
			
				|  |  | +For example, the following will submit a POST to "/logout" with a valid CSRF token:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(logout())
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +You can also customize the URL to post to.
 | 
	
		
			
				|  |  | +For example, the snippet below will submit a POST to "/signout" with a valid CSRF token:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(logout("/signout"))
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +=== SecurityMockMvcResultMatchers
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +At times it is desirable to make various security related assertions about a request.
 | 
	
		
			
				|  |  | +To accommodate this need, Spring Security Test support implements Spring MVC Test's `ResultMatcher` interface.
 | 
	
		
			
				|  |  | +In order to use Spring Security's `ResultMatcher` implementations ensure the following static import is used:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*;
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +==== Unauthenticated Assertion
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +At times it may be valuable to assert that there is no authenticated user associated with the result of a `MockMvc` invocation.
 | 
	
		
			
				|  |  | +For example, you might want to test submitting an invalid username and password and verify that no user is authenticated.
 | 
	
		
			
				|  |  | +You can easily do this with Spring Security's testing support using something like the following:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin().password("invalid"))
 | 
	
		
			
				|  |  | +    .andExpect(unauthenticated());
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +==== Authenticated Assertion
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +It is often times that we must assert that an authenticated user exists.
 | 
	
		
			
				|  |  | +For example, we may want to verify that we authenticated successfully.
 | 
	
		
			
				|  |  | +We could verify that a form based login was successful with the following snippet of code:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin())
 | 
	
		
			
				|  |  | +    .andExpect(authenticated());
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +If we wanted to assert the roles of the user, we could refine our previous code as shown below:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin().user("admin"))
 | 
	
		
			
				|  |  | +    .andExpect(authenticated().withRoles("USER","ADMIN"));
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Alternatively, we could verify the username:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin().user("admin"))
 | 
	
		
			
				|  |  | +    .andExpect(authenticated().withUsername("admin"));
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +We can also combine the assertions:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +[source,java]
 | 
	
		
			
				|  |  | +----
 | 
	
		
			
				|  |  | +mvc
 | 
	
		
			
				|  |  | +    .perform(formLogin().user("admin").roles("USER","ADMIN"))
 | 
	
		
			
				|  |  | +    .andExpect(authenticated().withUsername("admin"));
 | 
	
		
			
				|  |  | +----
 |