mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-01 09:42:13 +00:00
SEC-2984: WithMockUser authorities doc
This commit is contained in:
parent
e4517016ca
commit
b96cee7950
@ -14,7 +14,7 @@ public class HelloMessageService implements MessageService {
|
|||||||
@PreAuthorize("authenticated")
|
@PreAuthorize("authenticated")
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
Authentication authentication = SecurityContextHolder.getContext()
|
Authentication authentication = SecurityContextHolder.getContext()
|
||||||
.getAuthentication();
|
.getAuthentication();
|
||||||
return "Hello " + authentication;
|
return "Hello " + authentication;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ If we ran the following test, we would expect the following test will pass:
|
|||||||
----
|
----
|
||||||
@Test(expected = AuthenticationCredentialsNotFoundException.class)
|
@Test(expected = AuthenticationCredentialsNotFoundException.class)
|
||||||
public void getMessageUnauthenticated() {
|
public void getMessageUnauthenticated() {
|
||||||
messageService.getMessage();
|
messageService.getMessage();
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -72,8 +72,8 @@ The following test will be ran as a user with the username "user", the password
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser
|
@WithMockUser
|
||||||
public void getMessageWithMockUser() {
|
public void getMessageWithMockUser() {
|
||||||
String message = messageService.getMessage();
|
String message = messageService.getMessage();
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ The following test would run with the username "customUser". Again, the user doe
|
|||||||
@WithMockUser("customUsername")
|
@WithMockUser("customUsername")
|
||||||
public void getMessageWithMockUserCustomUsername() {
|
public void getMessageWithMockUserCustomUsername() {
|
||||||
String message = messageService.getMessage();
|
String message = messageService.getMessage();
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -111,6 +111,19 @@ public void getMessageWithMockUserCustomUser() {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
If we do not want the value to automatically be prefixed with ROLE_ we can leverage the authorities attribute.
|
||||||
|
For example, this test will be invoked with the username "admin" and the authorities "USER" and "ADMIN".
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin", authorities = { "ADMIN", "USER" })
|
||||||
|
public void getMessageWithMockUserCustomAuthorities() {
|
||||||
|
String message = messageService.getMessage();
|
||||||
|
...
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
Of course it can be a bit tedious placing the annotation on every test method.
|
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.
|
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".
|
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".
|
||||||
@ -191,7 +204,7 @@ You can find our `WithMockCustomUserSecurityContextFactory` implementation below
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
public class WithMockCustomUserSecurityContextFactory
|
public class WithMockCustomUserSecurityContextFactory
|
||||||
implements WithSecurityContextFactory<WithMockCustomUser> {
|
implements WithSecurityContextFactory<WithMockCustomUser> {
|
||||||
@Override
|
@Override
|
||||||
public SecurityContext createSecurityContext(WithMockCustomUser customUser) {
|
public SecurityContext createSecurityContext(WithMockCustomUser customUser) {
|
||||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||||
@ -214,24 +227,24 @@ For example, the `WithUserDetailsSecurityContextFactory` uses the `@Autowired` a
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
final class WithUserDetailsSecurityContextFactory
|
final class WithUserDetailsSecurityContextFactory
|
||||||
implements WithSecurityContextFactory<WithUserDetails> {
|
implements WithSecurityContextFactory<WithUserDetails> {
|
||||||
|
|
||||||
private UserDetailsService userDetailsService;
|
private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public WithUserDetailsSecurityContextFactory(UserDetailsService userDetailsService) {
|
public WithUserDetailsSecurityContextFactory(UserDetailsService userDetailsService) {
|
||||||
this.userDetailsService = userDetailsService;
|
this.userDetailsService = userDetailsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecurityContext createSecurityContext(WithUserDetails withUser) {
|
public SecurityContext createSecurityContext(WithUserDetails withUser) {
|
||||||
String username = withUser.value();
|
String username = withUser.value();
|
||||||
Assert.hasLength(username, "value() must be non empty String");
|
Assert.hasLength(username, "value() must be non empty String");
|
||||||
UserDetails principal = userDetailsService.loadUserByUsername(username);
|
UserDetails principal = userDetailsService.loadUserByUsername(username);
|
||||||
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
|
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
|
||||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||||
context.setAuthentication(authentication);
|
context.setAuthentication(authentication);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -260,20 +273,20 @@ import static org.springframework.security.test.web.servlet.setup.SecurityMockMv
|
|||||||
@WebAppConfiguration
|
@WebAppConfiguration
|
||||||
public class CsrfShowcaseTests {
|
public class CsrfShowcaseTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WebApplicationContext context;
|
private WebApplicationContext context;
|
||||||
|
|
||||||
private MockMvc mvc;
|
private MockMvc mvc;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
mvc = MockMvcBuilders
|
mvc = MockMvcBuilders
|
||||||
.webAppContextSetup(context)
|
.webAppContextSetup(context)
|
||||||
.apply(springSecurity()) // <1>
|
.apply(springSecurity()) // <1>
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
...
|
...
|
||||||
----
|
----
|
||||||
|
|
||||||
<1> `SecurityMockMvcConfigurers.springSecurity()` will perform all of the initial setup we need to integrate Spring Security with Spring MVC Test
|
<1> `SecurityMockMvcConfigurers.springSecurity()` will perform all of the initial setup we need to integrate Spring Security with Spring MVC Test
|
||||||
@ -299,7 +312,7 @@ To specify a valid CSRF token as a request parameter using the following:
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(post("/").with(csrf()))
|
.perform(post("/").with(csrf()))
|
||||||
----
|
----
|
||||||
|
|
||||||
If you like you can include CSRF token in the header instead:
|
If you like you can include CSRF token in the header instead:
|
||||||
@ -307,7 +320,7 @@ If you like you can include CSRF token in the header instead:
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(post("/").with(csrf().asHeader()))
|
.perform(post("/").with(csrf().asHeader()))
|
||||||
----
|
----
|
||||||
|
|
||||||
You can also test providing an invalid CSRF token using the following:
|
You can also test providing an invalid CSRF token using the following:
|
||||||
@ -315,7 +328,7 @@ You can also test providing an invalid CSRF token using the following:
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(post("/").with(csrf().useInvalidToken()))
|
.perform(post("/").with(csrf().useInvalidToken()))
|
||||||
----
|
----
|
||||||
|
|
||||||
[[test-mockmvc-securitycontextholder]]
|
[[test-mockmvc-securitycontextholder]]
|
||||||
@ -336,7 +349,7 @@ For example, the following will run as a user (which does not need to exist) wit
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/").with(user("user")))
|
.perform(get("/").with(user("user")))
|
||||||
----
|
----
|
||||||
|
|
||||||
You can easily make customizations.
|
You can easily make customizations.
|
||||||
@ -345,7 +358,7 @@ For example, the following will run as a user (which does not need to exist) wit
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
|
.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.
|
If you have a custom `UserDetails` that you would like to use, you can easily specify that as well.
|
||||||
@ -354,7 +367,7 @@ For example, the following will use the specified `UserDetails` (which does not
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/").with(user(userDetails)))
|
.perform(get("/").with(user(userDetails)))
|
||||||
----
|
----
|
||||||
|
|
||||||
If you want a custom `Authentication` (which does not need to exist) you can do so using the following:
|
If you want a custom `Authentication` (which does not need to exist) you can do so using the following:
|
||||||
@ -362,7 +375,7 @@ If you want a custom `Authentication` (which does not need to exist) you can do
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/").with(authentication(authentication)))
|
.perform(get("/").with(authentication(authentication)))
|
||||||
----
|
----
|
||||||
|
|
||||||
You can even customize the `SecurityContext` using the following:
|
You can even customize the `SecurityContext` using the following:
|
||||||
@ -370,7 +383,7 @@ You can even customize the `SecurityContext` using the following:
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/").with(securityContext(securityContext)))
|
.perform(get("/").with(securityContext(securityContext)))
|
||||||
----
|
----
|
||||||
|
|
||||||
We can also ensure to run as a specific user for every request by using `MockMvcBuilders`'s default request.
|
We can also ensure to run as a specific user for every request by using `MockMvcBuilders`'s default request.
|
||||||
@ -379,10 +392,10 @@ For example, the following will run as a user (which does not need to exist) wit
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc = MockMvcBuilders
|
mvc = MockMvcBuilders
|
||||||
.webAppContextSetup(context)
|
.webAppContextSetup(context)
|
||||||
.defaultRequest(get("/").with(user("user").roles("ADMIN")))
|
.defaultRequest(get("/").with(user("user").roles("ADMIN")))
|
||||||
.apply(springSecurity())
|
.apply(springSecurity())
|
||||||
.build();
|
.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.
|
If you find you are using the same user in many of your tests, it is recommended to move the user to a method.
|
||||||
@ -404,7 +417,7 @@ import static sample.CustomSecurityMockMvcRequestPostProcessors.*;
|
|||||||
...
|
...
|
||||||
|
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/").with(rob()))
|
.perform(get("/").with(rob()))
|
||||||
----
|
----
|
||||||
|
|
||||||
===== Running as a User in Spring MVC Test with Annotations
|
===== Running as a User in Spring MVC Test with Annotations
|
||||||
@ -417,9 +430,9 @@ For example, the following will run the test with the user with username "user",
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser
|
@WithMockUser
|
||||||
public void requestProtectedUrlWithUser() throws Exception {
|
public void requestProtectedUrlWithUser() throws Exception {
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/"))
|
.perform(get("/"))
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -430,9 +443,9 @@ Alternatively, the following will run the test with the user with username "user
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser(roles="ADMIN")
|
@WithMockUser(roles="ADMIN")
|
||||||
public void requestProtectedUrlWithUser() throws Exception {
|
public void requestProtectedUrlWithUser() throws Exception {
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/"))
|
.perform(get("/"))
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -445,7 +458,7 @@ For example, the snippet below:
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(get("/").with(httpBasic("user","password")))
|
.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:
|
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:
|
||||||
@ -474,7 +487,7 @@ For example, the following will submit a POST to "/login" with the username "use
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin())
|
.perform(formLogin())
|
||||||
----
|
----
|
||||||
|
|
||||||
It is easy to customize the request.
|
It is easy to customize the request.
|
||||||
@ -483,7 +496,7 @@ For example, the following will submit a POST to "/auth" with the username "admi
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin("/auth").user("admin").password("pass"))
|
.perform(formLogin("/auth").user("admin").password("pass"))
|
||||||
----
|
----
|
||||||
|
|
||||||
We can also customize the parameters names that the username and password are included on.
|
We can also customize the parameters names that the username and password are included on.
|
||||||
@ -492,7 +505,7 @@ For example, this is the above request modified to include the username on the H
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin("/auth").user("a","admin").password("p","pass"))
|
.perform(formLogin("/auth").user("a","admin").password("p","pass"))
|
||||||
----
|
----
|
||||||
|
|
||||||
[[test-logout]]
|
[[test-logout]]
|
||||||
@ -504,7 +517,7 @@ For example, the following will submit a POST to "/logout" with a valid CSRF tok
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(logout())
|
.perform(logout())
|
||||||
----
|
----
|
||||||
|
|
||||||
You can also customize the URL to post to.
|
You can also customize the URL to post to.
|
||||||
@ -513,7 +526,7 @@ For example, the snippet below will submit a POST to "/signout" with a valid CSR
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(logout("/signout"))
|
.perform(logout("/signout"))
|
||||||
----
|
----
|
||||||
|
|
||||||
=== SecurityMockMvcResultMatchers
|
=== SecurityMockMvcResultMatchers
|
||||||
@ -536,8 +549,8 @@ You can easily do this with Spring Security's testing support using something li
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin().password("invalid"))
|
.perform(formLogin().password("invalid"))
|
||||||
.andExpect(unauthenticated());
|
.andExpect(unauthenticated());
|
||||||
----
|
----
|
||||||
|
|
||||||
==== Authenticated Assertion
|
==== Authenticated Assertion
|
||||||
@ -549,8 +562,8 @@ We could verify that a form based login was successful with the following snippe
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin())
|
.perform(formLogin())
|
||||||
.andExpect(authenticated());
|
.andExpect(authenticated());
|
||||||
----
|
----
|
||||||
|
|
||||||
If we wanted to assert the roles of the user, we could refine our previous code as shown below:
|
If we wanted to assert the roles of the user, we could refine our previous code as shown below:
|
||||||
@ -558,8 +571,8 @@ If we wanted to assert the roles of the user, we could refine our previous code
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin().user("admin"))
|
.perform(formLogin().user("admin"))
|
||||||
.andExpect(authenticated().withRoles("USER","ADMIN"));
|
.andExpect(authenticated().withRoles("USER","ADMIN"));
|
||||||
----
|
----
|
||||||
|
|
||||||
Alternatively, we could verify the username:
|
Alternatively, we could verify the username:
|
||||||
@ -567,8 +580,8 @@ Alternatively, we could verify the username:
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin().user("admin"))
|
.perform(formLogin().user("admin"))
|
||||||
.andExpect(authenticated().withUsername("admin"));
|
.andExpect(authenticated().withUsername("admin"));
|
||||||
----
|
----
|
||||||
|
|
||||||
We can also combine the assertions:
|
We can also combine the assertions:
|
||||||
@ -576,6 +589,6 @@ We can also combine the assertions:
|
|||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
mvc
|
mvc
|
||||||
.perform(formLogin().user("admin").roles("USER","ADMIN"))
|
.perform(formLogin().user("admin").roles("USER","ADMIN"))
|
||||||
.andExpect(authenticated().withUsername("admin"));
|
.andExpect(authenticated().withUsername("admin"));
|
||||||
----
|
----
|
Loading…
x
Reference in New Issue
Block a user