|
|
|
@ -18,7 +18,9 @@ package org.springframework.security.test.web.servlet.response; |
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Collection; |
|
|
|
import java.util.Collection; |
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
import java.util.function.Consumer; |
|
|
|
import java.util.function.Consumer; |
|
|
|
|
|
|
|
import java.util.function.Predicate; |
|
|
|
|
|
|
|
|
|
|
|
import org.jspecify.annotations.NullUnmarked; |
|
|
|
import org.jspecify.annotations.NullUnmarked; |
|
|
|
import org.jspecify.annotations.Nullable; |
|
|
|
import org.jspecify.annotations.Nullable; |
|
|
|
@ -94,6 +96,8 @@ public final class SecurityMockMvcResultMatchers { |
|
|
|
|
|
|
|
|
|
|
|
private @Nullable Collection<? extends GrantedAuthority> expectedGrantedAuthorities; |
|
|
|
private @Nullable Collection<? extends GrantedAuthority> expectedGrantedAuthorities; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Predicate<GrantedAuthority> ignoreAuthorities = (authority) -> false; |
|
|
|
|
|
|
|
|
|
|
|
private @Nullable Consumer<Authentication> assertAuthentication; |
|
|
|
private @Nullable Consumer<Authentication> assertAuthentication; |
|
|
|
|
|
|
|
|
|
|
|
AuthenticatedMatcher() { |
|
|
|
AuthenticatedMatcher() { |
|
|
|
@ -132,7 +136,8 @@ public final class SecurityMockMvcResultMatchers { |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.expectedGrantedAuthorities != null) { |
|
|
|
if (this.expectedGrantedAuthorities != null) { |
|
|
|
AssertionErrors.assertTrue("Authentication cannot be null", auth != null); |
|
|
|
AssertionErrors.assertTrue("Authentication cannot be null", auth != null); |
|
|
|
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities(); |
|
|
|
Collection<? extends GrantedAuthority> authorities = new ArrayList<>(auth.getAuthorities()); |
|
|
|
|
|
|
|
authorities.removeIf(this.ignoreAuthorities); |
|
|
|
AssertionErrors.assertTrue( |
|
|
|
AssertionErrors.assertTrue( |
|
|
|
authorities + " does not contain the same authorities as " + this.expectedGrantedAuthorities, |
|
|
|
authorities + " does not contain the same authorities as " + this.expectedGrantedAuthorities, |
|
|
|
authorities.containsAll(this.expectedGrantedAuthorities)); |
|
|
|
authorities.containsAll(this.expectedGrantedAuthorities)); |
|
|
|
@ -212,16 +217,43 @@ public final class SecurityMockMvcResultMatchers { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Specifies the {@link Authentication#getAuthorities()} |
|
|
|
* Specifies the expected roles. |
|
|
|
|
|
|
|
* <p> |
|
|
|
|
|
|
|
* Since a set of authorities can contain more than just roles, this method |
|
|
|
|
|
|
|
* differs from {@link #withAuthorities} in that it only verifies the authorities |
|
|
|
|
|
|
|
* prefixed by {@code ROLE_}. Other authorities are ignored. |
|
|
|
|
|
|
|
* <p> |
|
|
|
|
|
|
|
* If you want to validate more than just roles, please use |
|
|
|
|
|
|
|
* {@link #withAuthorities}. |
|
|
|
* @param roles the roles. Each value is automatically prefixed with "ROLE_" |
|
|
|
* @param roles the roles. Each value is automatically prefixed with "ROLE_" |
|
|
|
* @return the {@link AuthenticatedMatcher} for further customization |
|
|
|
* @return the {@link AuthenticatedMatcher} for further customization |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public AuthenticatedMatcher withRoles(String... roles) { |
|
|
|
public AuthenticatedMatcher withRoles(String... roles) { |
|
|
|
Collection<GrantedAuthority> authorities = new ArrayList<>(); |
|
|
|
return withRoles("ROLE_", roles); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Specifies the expected roles. |
|
|
|
|
|
|
|
* <p> |
|
|
|
|
|
|
|
* Since a set of authorities can contain more than just roles, this method |
|
|
|
|
|
|
|
* differs from {@link #withAuthorities} in that it only verifies the authorities |
|
|
|
|
|
|
|
* prefixed by {@code ROLE_}. Other authorities are ignored. |
|
|
|
|
|
|
|
* <p> |
|
|
|
|
|
|
|
* If you want to validate more than just roles, please use |
|
|
|
|
|
|
|
* {@link #withAuthorities}. |
|
|
|
|
|
|
|
* @param rolePrefix the role prefix |
|
|
|
|
|
|
|
* @param roles the roles. Each value is automatically prefixed with the |
|
|
|
|
|
|
|
* {@code rolePrefix} |
|
|
|
|
|
|
|
* @return the {@link AuthenticatedMatcher} for further customization |
|
|
|
|
|
|
|
* @since 7.0 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public AuthenticatedMatcher withRoles(String rolePrefix, String[] roles) { |
|
|
|
|
|
|
|
List<GrantedAuthority> withPrefix = new ArrayList<>(); |
|
|
|
for (String role : roles) { |
|
|
|
for (String role : roles) { |
|
|
|
authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); |
|
|
|
withPrefix.add(new SimpleGrantedAuthority(rolePrefix + role)); |
|
|
|
} |
|
|
|
} |
|
|
|
return withAuthorities(authorities); |
|
|
|
this.ignoreAuthorities = (authority) -> !authority.getAuthority().startsWith(rolePrefix); |
|
|
|
|
|
|
|
return withAuthorities(withPrefix); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|