Fix mvcMatchers overriding previous paths
Closes gh-10956
This commit is contained in:
parent
67830f4111
commit
1959c25a03
|
@ -3290,20 +3290,26 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||||
*/
|
*/
|
||||||
public final class MvcMatchersRequestMatcherConfigurer extends RequestMatcherConfigurer {
|
public final class MvcMatchersRequestMatcherConfigurer extends RequestMatcherConfigurer {
|
||||||
|
|
||||||
|
private final List<MvcRequestMatcher> mvcMatchers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @param context the {@link ApplicationContext} to use
|
* @param context the {@link ApplicationContext} to use
|
||||||
* @param matchers the {@link MvcRequestMatcher} instances to set the servlet path
|
* @param mvcMatchers the {@link MvcRequestMatcher} instances to set the servlet
|
||||||
* on if {@link #servletPath(String)} is set.
|
* path on if {@link #servletPath(String)} is set.
|
||||||
|
* @param allMatchers the {@link RequestMatcher} instances to continue the
|
||||||
|
* configuration
|
||||||
*/
|
*/
|
||||||
private MvcMatchersRequestMatcherConfigurer(ApplicationContext context, List<MvcRequestMatcher> matchers) {
|
private MvcMatchersRequestMatcherConfigurer(ApplicationContext context, List<MvcRequestMatcher> mvcMatchers,
|
||||||
|
List<RequestMatcher> allMatchers) {
|
||||||
super(context);
|
super(context);
|
||||||
this.matchers = new ArrayList<>(matchers);
|
this.mvcMatchers = new ArrayList<>(mvcMatchers);
|
||||||
|
this.matchers = allMatchers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestMatcherConfigurer servletPath(String servletPath) {
|
public RequestMatcherConfigurer servletPath(String servletPath) {
|
||||||
for (RequestMatcher matcher : this.matchers) {
|
for (MvcRequestMatcher matcher : this.mvcMatchers) {
|
||||||
((MvcRequestMatcher) matcher).setServletPath(servletPath);
|
matcher.setServletPath(servletPath);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -3328,7 +3334,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||||
public MvcMatchersRequestMatcherConfigurer mvcMatchers(HttpMethod method, String... mvcPatterns) {
|
public MvcMatchersRequestMatcherConfigurer mvcMatchers(HttpMethod method, String... mvcPatterns) {
|
||||||
List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns);
|
List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns);
|
||||||
setMatchers(mvcMatchers);
|
setMatchers(mvcMatchers);
|
||||||
return new MvcMatchersRequestMatcherConfigurer(getContext(), mvcMatchers);
|
return new MvcMatchersRequestMatcherConfigurer(getContext(), mvcMatchers, this.matchers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,6 +26,8 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
@ -34,11 +36,13 @@ import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.web.PortMapperImpl;
|
import org.springframework.security.web.PortMapperImpl;
|
||||||
import org.springframework.security.web.RedirectStrategy;
|
import org.springframework.security.web.RedirectStrategy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
|
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
|
||||||
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
||||||
import org.springframework.security.web.access.channel.InsecureChannelProcessor;
|
import org.springframework.security.web.access.channel.InsecureChannelProcessor;
|
||||||
import org.springframework.security.web.access.channel.SecureChannelProcessor;
|
import org.springframework.security.web.access.channel.SecureChannelProcessor;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
@ -107,6 +111,24 @@ public class ChannelSecurityConfigurerTests {
|
||||||
this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/test"));
|
this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-10956
|
||||||
|
@Test
|
||||||
|
public void requestWhenRequiresChannelWithMultiMvcMatchersThenRedirectsToHttps() throws Exception {
|
||||||
|
this.spring.register(RequiresChannelMultiMvcMatchersConfig.class).autowire();
|
||||||
|
this.mvc.perform(get("/test-1")).andExpect(redirectedUrl("https://localhost/test-1"));
|
||||||
|
this.mvc.perform(get("/test-2")).andExpect(redirectedUrl("https://localhost/test-2"));
|
||||||
|
this.mvc.perform(get("/test-3")).andExpect(redirectedUrl("https://localhost/test-3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// gh-10956
|
||||||
|
@Test
|
||||||
|
public void requestWhenRequiresChannelWithMultiMvcMatchersInLambdaThenRedirectsToHttps() throws Exception {
|
||||||
|
this.spring.register(RequiresChannelMultiMvcMatchersInLambdaConfig.class).autowire();
|
||||||
|
this.mvc.perform(get("/test-1")).andExpect(redirectedUrl("https://localhost/test-1"));
|
||||||
|
this.mvc.perform(get("/test-2")).andExpect(redirectedUrl("https://localhost/test-2"));
|
||||||
|
this.mvc.perform(get("/test-3")).andExpect(redirectedUrl("https://localhost/test-3"));
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
|
static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@ -200,4 +222,59 @@ public class ChannelSecurityConfigurerTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@EnableWebMvc
|
||||||
|
static class RequiresChannelMultiMvcMatchersConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.portMapper()
|
||||||
|
.portMapper(new PortMapperImpl())
|
||||||
|
.and()
|
||||||
|
.requiresChannel()
|
||||||
|
.mvcMatchers("/test-1")
|
||||||
|
.requiresSecure()
|
||||||
|
.mvcMatchers("/test-2")
|
||||||
|
.requiresSecure()
|
||||||
|
.mvcMatchers("/test-3")
|
||||||
|
.requiresSecure()
|
||||||
|
.anyRequest()
|
||||||
|
.requiresInsecure();
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@EnableWebMvc
|
||||||
|
static class RequiresChannelMultiMvcMatchersInLambdaConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.portMapper((port) -> port
|
||||||
|
.portMapper(new PortMapperImpl())
|
||||||
|
)
|
||||||
|
.requiresChannel((channel) -> channel
|
||||||
|
.mvcMatchers("/test-1")
|
||||||
|
.requiresSecure()
|
||||||
|
.mvcMatchers("/test-2")
|
||||||
|
.requiresSecure()
|
||||||
|
.mvcMatchers("/test-3")
|
||||||
|
.requiresSecure()
|
||||||
|
.anyRequest()
|
||||||
|
.requiresInsecure()
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,10 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.mock.web.MockFilterChain;
|
import org.springframework.mock.web.MockFilterChain;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
@ -33,6 +36,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
@ -167,6 +171,38 @@ public class HttpSecurityRequestMatchersTests {
|
||||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestMatcherWhenMultiMvcMatcherInLambdaThenAllPathsAreDenied() throws Exception {
|
||||||
|
loadConfig(MultiMvcMatcherInLambdaConfig.class);
|
||||||
|
this.request.setRequestURI("/test-1");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
setup();
|
||||||
|
this.request.setRequestURI("/test-2");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
setup();
|
||||||
|
this.request.setRequestURI("/test-3");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestMatcherWhenMultiMvcMatcherThenAllPathsAreDenied() throws Exception {
|
||||||
|
loadConfig(MultiMvcMatcherConfig.class);
|
||||||
|
this.request.setRequestURI("/test-1");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
setup();
|
||||||
|
this.request.setRequestURI("/test-2");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
setup();
|
||||||
|
this.request.setRequestURI("/test-3");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
public void loadConfig(Class<?>... configs) {
|
public void loadConfig(Class<?>... configs) {
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.register(configs);
|
this.context.register(configs);
|
||||||
|
@ -175,6 +211,101 @@ public class HttpSecurityRequestMatchersTests {
|
||||||
this.context.getAutowireCapableBeanFactory().autowireBean(this);
|
this.context.getAutowireCapableBeanFactory().autowireBean(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Configuration
|
||||||
|
@EnableWebMvc
|
||||||
|
static class MultiMvcMatcherInLambdaConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
|
SecurityFilterChain first(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.requestMatchers((requests) -> requests
|
||||||
|
.mvcMatchers("/test-1")
|
||||||
|
.mvcMatchers("/test-2")
|
||||||
|
.mvcMatchers("/test-3")
|
||||||
|
)
|
||||||
|
.authorizeRequests((authorize) -> authorize.anyRequest().denyAll())
|
||||||
|
.httpBasic(withDefaults());
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain second(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.requestMatchers((requests) -> requests
|
||||||
|
.mvcMatchers("/test-1")
|
||||||
|
)
|
||||||
|
.authorizeRequests((authorize) -> authorize
|
||||||
|
.anyRequest().permitAll()
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
static class PathController {
|
||||||
|
|
||||||
|
@RequestMapping({ "/test-1", "/test-2", "/test-3" })
|
||||||
|
String path() {
|
||||||
|
return "path";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Configuration
|
||||||
|
@EnableWebMvc
|
||||||
|
static class MultiMvcMatcherConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
|
SecurityFilterChain first(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.requestMatchers()
|
||||||
|
.mvcMatchers("/test-1")
|
||||||
|
.mvcMatchers("/test-2")
|
||||||
|
.mvcMatchers("/test-3")
|
||||||
|
.and()
|
||||||
|
.authorizeRequests()
|
||||||
|
.anyRequest().denyAll()
|
||||||
|
.and()
|
||||||
|
.httpBasic(withDefaults());
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain second(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.requestMatchers()
|
||||||
|
.mvcMatchers("/test-1")
|
||||||
|
.and()
|
||||||
|
.authorizeRequests()
|
||||||
|
.anyRequest().permitAll();
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
static class PathController {
|
||||||
|
|
||||||
|
@RequestMapping({ "/test-1", "/test-2", "/test-3" })
|
||||||
|
String path() {
|
||||||
|
return "path";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web.configurers;
|
package org.springframework.security.config.annotation.web.configurers;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -23,16 +25,24 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.mock.web.MockFilterChain;
|
import org.springframework.mock.web.MockFilterChain;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
@ -125,6 +135,35 @@ public class UrlAuthorizationConfigurerTests {
|
||||||
loadConfig(AnonymousUrlAuthorizationConfig.class);
|
loadConfig(AnonymousUrlAuthorizationConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-10956
|
||||||
|
@Test
|
||||||
|
public void multiMvcMatchersConfig() throws Exception {
|
||||||
|
loadConfig(MultiMvcMatcherConfig.class);
|
||||||
|
this.request.addHeader("Authorization",
|
||||||
|
"Basic " + new String(Base64.getEncoder().encode("user:password".getBytes())));
|
||||||
|
this.request.setRequestURI("/test-1");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
setup();
|
||||||
|
this.request.addHeader("Authorization",
|
||||||
|
"Basic " + new String(Base64.getEncoder().encode("user:password".getBytes())));
|
||||||
|
this.request.setRequestURI("/test-2");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
setup();
|
||||||
|
this.request.addHeader("Authorization",
|
||||||
|
"Basic " + new String(Base64.getEncoder().encode("user:password".getBytes())));
|
||||||
|
this.request.setRequestURI("/test-3");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
setup();
|
||||||
|
this.request.addHeader("Authorization",
|
||||||
|
"Basic " + new String(Base64.getEncoder().encode("user:password".getBytes())));
|
||||||
|
this.request.setRequestURI("/test-x");
|
||||||
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
|
}
|
||||||
|
|
||||||
public void loadConfig(Class<?>... configs) {
|
public void loadConfig(Class<?>... configs) {
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.register(configs);
|
this.context.register(configs);
|
||||||
|
@ -228,4 +267,41 @@ public class UrlAuthorizationConfigurerTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@EnableWebMvc
|
||||||
|
static class MultiMvcMatcherConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain security(HttpSecurity http, ApplicationContext context) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.httpBasic(Customizer.withDefaults())
|
||||||
|
.apply(new UrlAuthorizationConfigurer<>(context)).getRegistry()
|
||||||
|
.mvcMatchers("/test-1").hasRole("ADMIN")
|
||||||
|
.mvcMatchers("/test-2").hasRole("ADMIN")
|
||||||
|
.mvcMatchers("/test-3").hasRole("ADMIN")
|
||||||
|
.anyRequest().hasRole("USER");
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
UserDetailsService userDetailsService() {
|
||||||
|
UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER")
|
||||||
|
.build();
|
||||||
|
return new InMemoryUserDetailsManager(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
static class PathController {
|
||||||
|
|
||||||
|
@RequestMapping({ "/test-1", "/test-2", "/test-3", "/test-x" })
|
||||||
|
String path() {
|
||||||
|
return "path";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue