SecurityMockMvcResultMatchers.withAuthorities(String...)
CodeQL Advanced / codeql-analysis-call (push) Waiting to run
Details
CI / Build (17, ubuntu-latest) (push) Waiting to run
Details
CI / Build (17, windows-latest) (push) Waiting to run
Details
CI / Deploy Artifacts (push) Blocked by required conditions
Details
CI / Deploy Docs (push) Blocked by required conditions
Details
CI / Deploy Schema (push) Blocked by required conditions
Details
CI / Perform Release (push) Blocked by required conditions
Details
CI / Send Notification (push) Blocked by required conditions
Details
Deploy Docs / build (push) Waiting to run
Details
CodeQL Advanced / codeql-analysis-call (push) Waiting to run
Details
CI / Build (17, ubuntu-latest) (push) Waiting to run
Details
CI / Build (17, windows-latest) (push) Waiting to run
Details
CI / Deploy Artifacts (push) Blocked by required conditions
Details
CI / Deploy Docs (push) Blocked by required conditions
Details
CI / Deploy Schema (push) Blocked by required conditions
Details
CI / Perform Release (push) Blocked by required conditions
Details
CI / Send Notification (push) Blocked by required conditions
Details
Deploy Docs / build (push) Waiting to run
Details
Closes gh-17974
This commit is contained in:
parent
0e99324c43
commit
7f10897de3
|
@ -70,6 +70,10 @@ http.csrf((csrf) -> csrf.spa());
|
||||||
* Made so that SLO still returns `<saml2:LogoutResponse>` even when validation fails
|
* Made so that SLO still returns `<saml2:LogoutResponse>` even when validation fails
|
||||||
* Removed Open SAML 4 support; applications should migrate to Open SAML 5
|
* Removed Open SAML 4 support; applications should migrate to Open SAML 5
|
||||||
|
|
||||||
|
== Test
|
||||||
|
|
||||||
|
* https://github.com/spring-projects/spring-security/issues/17974[Add SecurityMockMvcResultMatchers.withAuthorities(String...)]
|
||||||
|
|
||||||
== Web
|
== Web
|
||||||
|
|
||||||
* Removed `MvcRequestMatcher` and `AntPathRequestMatcher` in favor of `PathPatternRequestMatcher`
|
* Removed `MvcRequestMatcher` and `AntPathRequestMatcher` in favor of `PathPatternRequestMatcher`
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.security.test.web.servlet.response;
|
package org.springframework.security.test.web.servlet.response;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -38,6 +39,7 @@ import org.springframework.test.util.AssertionErrors;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.ResultMatcher;
|
import org.springframework.test.web.servlet.ResultMatcher;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Security related {@link MockMvc} {@link ResultMatcher}s.
|
* Security related {@link MockMvc} {@link ResultMatcher}s.
|
||||||
|
@ -96,6 +98,8 @@ public final class SecurityMockMvcResultMatchers {
|
||||||
|
|
||||||
private @Nullable Collection<? extends GrantedAuthority> expectedGrantedAuthorities;
|
private @Nullable Collection<? extends GrantedAuthority> expectedGrantedAuthorities;
|
||||||
|
|
||||||
|
private @Nullable Collection<String> expectedAuthorities;
|
||||||
|
|
||||||
private Predicate<GrantedAuthority> ignoreAuthorities = (authority) -> false;
|
private Predicate<GrantedAuthority> ignoreAuthorities = (authority) -> false;
|
||||||
|
|
||||||
private @Nullable Consumer<Authentication> assertAuthentication;
|
private @Nullable Consumer<Authentication> assertAuthentication;
|
||||||
|
@ -145,6 +149,20 @@ public final class SecurityMockMvcResultMatchers {
|
||||||
this.expectedGrantedAuthorities + " does not contain the same authorities as " + authorities,
|
this.expectedGrantedAuthorities + " does not contain the same authorities as " + authorities,
|
||||||
this.expectedGrantedAuthorities.containsAll(authorities));
|
this.expectedGrantedAuthorities.containsAll(authorities));
|
||||||
}
|
}
|
||||||
|
if (this.expectedAuthorities != null) {
|
||||||
|
AssertionErrors.assertTrue("Authentication cannot be null", auth != null);
|
||||||
|
List<String> authorities = auth.getAuthorities()
|
||||||
|
.stream()
|
||||||
|
.filter(Predicate.not(this.ignoreAuthorities))
|
||||||
|
.map(GrantedAuthority::getAuthority)
|
||||||
|
.toList();
|
||||||
|
AssertionErrors.assertTrue(
|
||||||
|
authorities + " does not contain the same authorities as " + this.expectedAuthorities,
|
||||||
|
this.expectedAuthorities.containsAll(authorities));
|
||||||
|
AssertionErrors.assertTrue(
|
||||||
|
this.expectedAuthorities + " does not contain the same authorities as " + authorities,
|
||||||
|
authorities.containsAll(this.expectedAuthorities));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -206,6 +224,17 @@ public final class SecurityMockMvcResultMatchers {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the {@link GrantedAuthority#getAuthority()}
|
||||||
|
* @param authorities the authorityNames
|
||||||
|
* @return the {@link AuthenticatedMatcher} for further customization
|
||||||
|
*/
|
||||||
|
public AuthenticatedMatcher withAuthorities(String... authorities) {
|
||||||
|
Assert.notNull(authorities, "authorities cannot be null");
|
||||||
|
this.expectedAuthorities = Arrays.asList(authorities);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the {@link Authentication#getAuthorities()}
|
* Specifies the {@link Authentication#getAuthorities()}
|
||||||
* @param expected the {@link Authentication#getAuthorities()}
|
* @param expected the {@link Authentication#getAuthorities()}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.core.GrantedAuthorities;
|
import org.springframework.security.core.GrantedAuthorities;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
@ -53,6 +54,8 @@ import static org.springframework.security.test.web.servlet.setup.SecurityMockMv
|
||||||
@WebAppConfiguration
|
@WebAppConfiguration
|
||||||
public class SecurityMockWithAuthoritiesMvcResultMatchersTests {
|
public class SecurityMockWithAuthoritiesMvcResultMatchersTests {
|
||||||
|
|
||||||
|
private static final String ROLE_CUSTOM = "ROLE_CUSTOM";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WebApplicationContext context;
|
private WebApplicationContext context;
|
||||||
|
|
||||||
|
@ -80,6 +83,12 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests {
|
||||||
() -> this.mockMvc.perform(formLogin()).andExpect(authenticated().withAuthorities(grantedAuthorities)));
|
() -> this.mockMvc.perform(formLogin()).andExpect(authenticated().withAuthorities(grantedAuthorities)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withAuthoritiesStringSupportsCustomAuthority() throws Exception {
|
||||||
|
this.mockMvc.perform(formLogin().user("custom"))
|
||||||
|
.andExpect(authenticated().withAuthorities(ROLE_CUSTOM, GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY));
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
|
@ -89,7 +98,8 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests {
|
||||||
UserDetailsService userDetailsService() {
|
UserDetailsService userDetailsService() {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("ADMIN", "SELLER").build();
|
UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("ADMIN", "SELLER").build();
|
||||||
return new InMemoryUserDetailsManager(user);
|
UserDetails customAuthorityUser = User.withDefaultPasswordEncoder().username("custom").password("password").authorities(new CustomAuthority(ROLE_CUSTOM)).build();
|
||||||
|
return new InMemoryUserDetailsManager(user, customAuthorityUser);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,4 +115,25 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom {@link GrantedAuthority} for testing.
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
static class CustomAuthority implements GrantedAuthority {
|
||||||
|
|
||||||
|
private final String authority;
|
||||||
|
|
||||||
|
CustomAuthority(String authority) {
|
||||||
|
this.authority = authority;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthority() {
|
||||||
|
return this.authority;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue