diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java b/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java
index 818d9f0e7c..9144915ada 100644
--- a/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java
+++ b/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java
@@ -70,14 +70,33 @@ public @interface WithMockUser {
String username() default "";
/**
+ *
* The roles to use. The default is "USER". A {@link GrantedAuthority} will be created
* for each value within roles. Each value in roles will automatically be prefixed
* with "ROLE_". For example, the default will result in "ROLE_USER" being used.
+ *
+ *
+ * If {@link #authorities()} is specified this property cannot be changed from the default.
+ *
*
* @return
*/
String[] roles() default { "USER" };
+ /**
+ *
+ * The authorities to use. A {@link GrantedAuthority} will be created for each value.
+ *
+ *
+ *
+ * If this property is specified then {@link #roles()} is not used. This differs from
+ * {@link #roles()} in that it does not prefix the values passed in automatically.
+ *
+ *
+ * @return
+ */
+ String[] authorities() default {};
+
/**
* The password to be used. The default is "password".
* @return
diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java b/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java
index 30a5881a85..9ac88da90d 100644
--- a/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java
+++ b/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java
@@ -16,6 +16,7 @@
package org.springframework.security.test.context.support;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -44,16 +45,26 @@ final class WithMockUserSecurityContextFactory implements
throw new IllegalArgumentException(withUser
+ " cannot have null username on both username and value properites");
}
- List authorities = new ArrayList();
- for (String role : withUser.roles()) {
- if (role.startsWith("ROLE_")) {
- throw new IllegalArgumentException("roles cannot start with ROLE_ Got "
- + role);
+
+ List grantedAuthorities = new ArrayList();
+ for (String authority : withUser.authorities()) {
+ grantedAuthorities.add(new SimpleGrantedAuthority(authority));
+ }
+
+ if(grantedAuthorities.isEmpty()) {
+ for (String role : withUser.roles()) {
+ if (role.startsWith("ROLE_")) {
+ throw new IllegalArgumentException("roles cannot start with ROLE_ Got "
+ + role);
+ }
+ grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + role));
}
- authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
+ } else if(!(withUser.roles().length == 1 && "USER".equals(withUser.roles()[0]))) {
+ throw new IllegalStateException("You cannot define roles attribute "+ Arrays.asList(withUser.roles())+" with authorities attribute "+ Arrays.asList(withUser.authorities()));
}
+
User principal = new User(username, withUser.password(), true, true, true, true,
- authorities);
+ grantedAuthorities);
Authentication authentication = new UsernamePasswordAuthenticationToken(
principal, principal.getPassword(), principal.getAuthorities());
SecurityContext context = SecurityContextHolder.createEmptyContext();
diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java
index f95137c77a..9cd1a206e4 100644
--- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java
+++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java
@@ -67,6 +67,13 @@ public class WithMockUserTests {
.contains("ROLE_ADMIN");
}
+ @Test
+ @WithMockUser(username = "admin", authorities = { "ADMIN", "USER" })
+ public void getMessageWithMockUserCustomAuthorities() {
+ String message = messageService.getMessage();
+ assertThat(message).contains("admin").contains("ADMIN").contains("USER").doesNotContain("ROLE_");
+ }
+
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan(basePackageClasses = HelloMessageService.class)
static class Config {
diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java
index 2cf94b7070..6c844092c9 100644
--- a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java
+++ b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java
@@ -47,6 +47,7 @@ public class WithMockUserSecurityContextFactoryTests {
when(withUser.value()).thenReturn("valueUser");
when(withUser.password()).thenReturn("password");
when(withUser.roles()).thenReturn(new String[] { "USER" });
+ when(withUser.authorities()).thenReturn(new String[] {});
assertThat(factory.createSecurityContext(withUser).getAuthentication().getName())
.isEqualTo(withUser.value());
@@ -58,6 +59,7 @@ public class WithMockUserSecurityContextFactoryTests {
when(withUser.username()).thenReturn("customUser");
when(withUser.password()).thenReturn("password");
when(withUser.roles()).thenReturn(new String[] { "USER" });
+ when(withUser.authorities()).thenReturn(new String[] {});
assertThat(factory.createSecurityContext(withUser).getAuthentication().getName())
.isEqualTo(withUser.username());
@@ -68,6 +70,7 @@ public class WithMockUserSecurityContextFactoryTests {
when(withUser.value()).thenReturn("valueUser");
when(withUser.password()).thenReturn("password");
when(withUser.roles()).thenReturn(new String[] { "USER", "CUSTOM" });
+ when(withUser.authorities()).thenReturn(new String[] {});
assertThat(
factory.createSecurityContext(withUser).getAuthentication()
@@ -75,11 +78,35 @@ public class WithMockUserSecurityContextFactoryTests {
"ROLE_USER", "ROLE_CUSTOM");
}
+ @Test
+ public void authoritiesWorks() {
+ when(withUser.value()).thenReturn("valueUser");
+ when(withUser.password()).thenReturn("password");
+ when(withUser.roles()).thenReturn(new String[] { "USER" });
+ when(withUser.authorities()).thenReturn(new String[] { "USER", "CUSTOM" });
+
+ assertThat(
+ factory.createSecurityContext(withUser).getAuthentication()
+ .getAuthorities()).onProperty("authority").containsOnly(
+ "USER", "CUSTOM");
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void authoritiesAndRolesInvalid() {
+ when(withUser.value()).thenReturn("valueUser");
+ when(withUser.password()).thenReturn("password");
+ when(withUser.roles()).thenReturn(new String[] { "CUSTOM" });
+ when(withUser.authorities()).thenReturn(new String[] { "USER", "CUSTOM" });
+
+ factory.createSecurityContext(withUser);
+ }
+
@Test(expected = IllegalArgumentException.class)
public void rolesWithRolePrefixFails() {
when(withUser.value()).thenReturn("valueUser");
when(withUser.password()).thenReturn("password");
when(withUser.roles()).thenReturn(new String[] { "ROLE_FAIL" });
+ when(withUser.authorities()).thenReturn(new String[] {});
factory.createSecurityContext(withUser);
}