Move PathPatternRequestMatcher.Builder to Shared Object
This commit changes the DSL to look for a shared object instead of publishing a bean for PathPatternRequestMatcher.Builder. Closes gh-17746
This commit is contained in:
		
							parent
							
								
									006f638c0a
								
							
						
					
					
						commit
						aeb2dbc2b6
					
				|  | @ -27,11 +27,13 @@ import org.apache.commons.logging.LogFactory; | ||||||
| import org.springframework.context.ApplicationContext; | import org.springframework.context.ApplicationContext; | ||||||
| import org.springframework.http.HttpMethod; | import org.springframework.http.HttpMethod; | ||||||
| import org.springframework.lang.Nullable; | import org.springframework.lang.Nullable; | ||||||
|  | import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; | ||||||
| import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; | import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; | ||||||
| import org.springframework.security.web.util.matcher.AnyRequestMatcher; | import org.springframework.security.web.util.matcher.AnyRequestMatcher; | ||||||
| import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher; | import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher; | ||||||
| import org.springframework.security.web.util.matcher.RequestMatcher; | import org.springframework.security.web.util.matcher.RequestMatcher; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
|  | import org.springframework.util.function.ThrowingSupplier; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A base class for registering {@link RequestMatcher}'s. For example, it might allow for |  * A base class for registering {@link RequestMatcher}'s. For example, it might allow for | ||||||
|  | @ -52,6 +54,8 @@ public abstract class AbstractRequestMatcherRegistry<C> { | ||||||
| 
 | 
 | ||||||
| 	private final Log logger = LogFactory.getLog(getClass()); | 	private final Log logger = LogFactory.getLog(getClass()); | ||||||
| 
 | 
 | ||||||
|  | 	private PathPatternRequestMatcher.Builder requestMatcherBuilder; | ||||||
|  | 
 | ||||||
| 	protected final void setApplicationContext(ApplicationContext context) { | 	protected final void setApplicationContext(ApplicationContext context) { | ||||||
| 		this.context = context; | 		this.context = context; | ||||||
| 	} | 	} | ||||||
|  | @ -140,7 +144,7 @@ public abstract class AbstractRequestMatcherRegistry<C> { | ||||||
| 					+ "Spring Security, leaving out the leading slash will result in an exception."); | 					+ "Spring Security, leaving out the leading slash will result in an exception."); | ||||||
| 		} | 		} | ||||||
| 		Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest"); | 		Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest"); | ||||||
| 		PathPatternRequestMatcher.Builder builder = this.context.getBean(PathPatternRequestMatcher.Builder.class); | 		PathPatternRequestMatcher.Builder builder = getRequestMatcherBuilder(); | ||||||
| 		List<RequestMatcher> matchers = new ArrayList<>(); | 		List<RequestMatcher> matchers = new ArrayList<>(); | ||||||
| 		for (String pattern : patterns) { | 		for (String pattern : patterns) { | ||||||
| 			matchers.add(builder.matcher(method, pattern)); | 			matchers.add(builder.matcher(method, pattern)); | ||||||
|  | @ -148,6 +152,23 @@ public abstract class AbstractRequestMatcherRegistry<C> { | ||||||
| 		return requestMatchers(matchers.toArray(new RequestMatcher[0])); | 		return requestMatchers(matchers.toArray(new RequestMatcher[0])); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	private PathPatternRequestMatcher.Builder getRequestMatcherBuilder() { | ||||||
|  | 		if (this.requestMatcherBuilder != null) { | ||||||
|  | 			return this.requestMatcherBuilder; | ||||||
|  | 		} | ||||||
|  | 		this.requestMatcherBuilder = this.context.getBeanProvider(PathPatternRequestMatcher.Builder.class) | ||||||
|  | 			.getIfUnique(() -> constructRequestMatcherBuilder(this.context)); | ||||||
|  | 		return this.requestMatcherBuilder; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private PathPatternRequestMatcher.Builder constructRequestMatcherBuilder(ApplicationContext context) { | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder = new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		requestMatcherBuilder.setApplicationContext(context); | ||||||
|  | 		requestMatcherBuilder.setBeanFactory(context.getAutowireCapableBeanFactory()); | ||||||
|  | 		requestMatcherBuilder.setBeanName(requestMatcherBuilder.toString()); | ||||||
|  | 		return ThrowingSupplier.of(requestMatcherBuilder::getObject).get(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	private boolean anyPathsDontStartWithLeadingSlash(String... patterns) { | 	private boolean anyPathsDontStartWithLeadingSlash(String... patterns) { | ||||||
| 		for (String pattern : patterns) { | 		for (String pattern : patterns) { | ||||||
| 			if (!pattern.startsWith("/")) { | 			if (!pattern.startsWith("/")) { | ||||||
|  |  | ||||||
|  | @ -2058,7 +2058,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul | ||||||
| 	 */ | 	 */ | ||||||
| 	public HttpSecurity securityMatcher(String... patterns) { | 	public HttpSecurity securityMatcher(String... patterns) { | ||||||
| 		List<RequestMatcher> matchers = new ArrayList<>(); | 		List<RequestMatcher> matchers = new ArrayList<>(); | ||||||
| 		PathPatternRequestMatcher.Builder builder = getContext().getBean(PathPatternRequestMatcher.Builder.class); | 		PathPatternRequestMatcher.Builder builder = getSharedObject(PathPatternRequestMatcher.Builder.class); | ||||||
| 		for (String pattern : patterns) { | 		for (String pattern : patterns) { | ||||||
| 			matchers.add(builder.matcher(pattern)); | 			matchers.add(builder.matcher(pattern)); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -1,31 +0,0 @@ | ||||||
| /* |  | ||||||
|  * Copyright 2004-present the original author or authors. |  | ||||||
|  * |  | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *      https://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package org.springframework.security.config.annotation.web.configuration; |  | ||||||
| 
 |  | ||||||
| import org.springframework.context.annotation.Bean; |  | ||||||
| import org.springframework.context.annotation.Fallback; |  | ||||||
| import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; |  | ||||||
| 
 |  | ||||||
| class AuthorizationConfiguration { |  | ||||||
| 
 |  | ||||||
| 	@Bean |  | ||||||
| 	@Fallback |  | ||||||
| 	PathPatternRequestMatcherBuilderFactoryBean pathPatternRequestMatcherBuilder() { |  | ||||||
| 		return new PathPatternRequestMatcherBuilderFactoryBean(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -83,7 +83,7 @@ import org.springframework.security.web.SecurityFilterChain; | ||||||
| @Target(ElementType.TYPE) | @Target(ElementType.TYPE) | ||||||
| @Documented | @Documented | ||||||
| @Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class, | @Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class, | ||||||
| 		HttpSecurityConfiguration.class, ObservationImportSelector.class, AuthorizationConfiguration.class }) | 		HttpSecurityConfiguration.class, ObservationImportSelector.class }) | ||||||
| @EnableGlobalAuthentication | @EnableGlobalAuthentication | ||||||
| public @interface EnableWebSecurity { | public @interface EnableWebSecurity { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -38,12 +38,15 @@ import org.springframework.security.config.annotation.authentication.configurers | ||||||
| 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.configurers.AbstractHttpConfigurer; | import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; | ||||||
| import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer; | import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer; | ||||||
|  | import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; | ||||||
| import org.springframework.security.core.context.SecurityContextHolder; | import org.springframework.security.core.context.SecurityContextHolder; | ||||||
| import org.springframework.security.core.context.SecurityContextHolderStrategy; | import org.springframework.security.core.context.SecurityContextHolderStrategy; | ||||||
| import org.springframework.security.core.userdetails.UserDetailsService; | import org.springframework.security.core.userdetails.UserDetailsService; | ||||||
| import org.springframework.security.crypto.factory.PasswordEncoderFactories; | import org.springframework.security.crypto.factory.PasswordEncoderFactories; | ||||||
| import org.springframework.security.crypto.password.PasswordEncoder; | import org.springframework.security.crypto.password.PasswordEncoder; | ||||||
| import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; | import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; | ||||||
|  | import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; | ||||||
|  | import org.springframework.util.function.ThrowingSupplier; | ||||||
| import org.springframework.web.accept.ContentNegotiationStrategy; | import org.springframework.web.accept.ContentNegotiationStrategy; | ||||||
| import org.springframework.web.accept.HeaderContentNegotiationStrategy; | import org.springframework.web.accept.HeaderContentNegotiationStrategy; | ||||||
| import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||||||
|  | @ -161,9 +164,18 @@ class HttpSecurityConfiguration { | ||||||
| 		Map<Class<?>, Object> sharedObjects = new HashMap<>(); | 		Map<Class<?>, Object> sharedObjects = new HashMap<>(); | ||||||
| 		sharedObjects.put(ApplicationContext.class, this.context); | 		sharedObjects.put(ApplicationContext.class, this.context); | ||||||
| 		sharedObjects.put(ContentNegotiationStrategy.class, this.contentNegotiationStrategy); | 		sharedObjects.put(ContentNegotiationStrategy.class, this.contentNegotiationStrategy); | ||||||
|  | 		sharedObjects.put(PathPatternRequestMatcher.Builder.class, constructRequestMatcherBuilder(this.context)); | ||||||
| 		return sharedObjects; | 		return sharedObjects; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	private PathPatternRequestMatcher.Builder constructRequestMatcherBuilder(ApplicationContext context) { | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder = new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		requestMatcherBuilder.setApplicationContext(context); | ||||||
|  | 		requestMatcherBuilder.setBeanFactory(context.getAutowireCapableBeanFactory()); | ||||||
|  | 		requestMatcherBuilder.setBeanName(requestMatcherBuilder.toString()); | ||||||
|  | 		return ThrowingSupplier.of(requestMatcherBuilder::getObject).get(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder { | 	static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder { | ||||||
| 
 | 
 | ||||||
| 		private PasswordEncoder defaultPasswordEncoder; | 		private PasswordEncoder defaultPasswordEncoder; | ||||||
|  |  | ||||||
|  | @ -39,8 +39,6 @@ public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, | ||||||
| 
 | 
 | ||||||
| 	private SecurityContextHolderStrategy securityContextHolderStrategy; | 	private SecurityContextHolderStrategy securityContextHolderStrategy; | ||||||
| 
 | 
 | ||||||
| 	private PathPatternRequestMatcher.Builder requestMatcherBuilder; |  | ||||||
| 
 |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Disables the {@link AbstractHttpConfigurer} by removing it. After doing so a fresh | 	 * Disables the {@link AbstractHttpConfigurer} by removing it. After doing so a fresh | ||||||
| 	 * version of the configuration can be applied. | 	 * version of the configuration can be applied. | ||||||
|  | @ -69,12 +67,7 @@ public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	protected PathPatternRequestMatcher.Builder getRequestMatcherBuilder() { | 	protected PathPatternRequestMatcher.Builder getRequestMatcherBuilder() { | ||||||
| 		if (this.requestMatcherBuilder != null) { | 		return getBuilder().getSharedObject(PathPatternRequestMatcher.Builder.class); | ||||||
| 			return this.requestMatcherBuilder; |  | ||||||
| 		} |  | ||||||
| 		ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class); |  | ||||||
| 		this.requestMatcherBuilder = context.getBean(PathPatternRequestMatcher.Builder.class); |  | ||||||
| 		return this.requestMatcherBuilder; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ | ||||||
| package org.springframework.security.config.annotation.web; | package org.springframework.security.config.annotation.web; | ||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.stream.Stream; | ||||||
| 
 | 
 | ||||||
| import jakarta.servlet.DispatcherType; | import jakarta.servlet.DispatcherType; | ||||||
| import org.junit.jupiter.api.BeforeEach; | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | @ -68,8 +69,8 @@ public class AbstractRequestMatcherRegistryTests { | ||||||
| 		ObjectProvider<ObjectPostProcessor<Object>> given = this.context.getBeanProvider(type); | 		ObjectProvider<ObjectPostProcessor<Object>> given = this.context.getBeanProvider(type); | ||||||
| 		given(given).willReturn(postProcessors); | 		given(given).willReturn(postProcessors); | ||||||
| 		given(postProcessors.getObject()).willReturn(NO_OP_OBJECT_POST_PROCESSOR); | 		given(postProcessors.getObject()).willReturn(NO_OP_OBJECT_POST_PROCESSOR); | ||||||
| 		given(this.context.getBean(PathPatternRequestMatcher.Builder.class)) | 		given(this.context.getBeanProvider(PathPatternRequestMatcher.Builder.class)) | ||||||
| 			.willReturn(PathPatternRequestMatcher.withDefaults()); | 			.willReturn(new SingleObjectProvider<>(PathPatternRequestMatcher.withDefaults())); | ||||||
| 		this.matcherRegistry.setApplicationContext(this.context); | 		this.matcherRegistry.setApplicationContext(this.context); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -165,4 +166,19 @@ public class AbstractRequestMatcherRegistryTests { | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	private static final class SingleObjectProvider<T> implements ObjectProvider<T> { | ||||||
|  | 
 | ||||||
|  | 		private final T object; | ||||||
|  | 
 | ||||||
|  | 		private SingleObjectProvider(T object) { | ||||||
|  | 			this.object = object; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		@Override | ||||||
|  | 		public Stream<T> stream() { | ||||||
|  | 			return Stream.of(this.object); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -54,6 +54,7 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults; | ||||||
| import org.springframework.security.config.observation.SecurityObservationSettings; | import org.springframework.security.config.observation.SecurityObservationSettings; | ||||||
| import org.springframework.security.config.test.SpringTestContext; | 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.config.web.PathPatternRequestMatcherBuilderFactoryBean; | ||||||
| import org.springframework.security.core.Authentication; | import org.springframework.security.core.Authentication; | ||||||
| import org.springframework.security.core.authority.AuthorityUtils; | import org.springframework.security.core.authority.AuthorityUtils; | ||||||
| import org.springframework.security.core.authority.SimpleGrantedAuthority; | import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||||||
|  | @ -1051,12 +1052,19 @@ public class AuthorizeHttpRequestsConfigurerTests { | ||||||
| 	@EnableWebSecurity | 	@EnableWebSecurity | ||||||
| 	static class ServletPathConfig { | 	static class ServletPathConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requesMatcherBuilder() { | ||||||
|  | 			PathPatternRequestMatcherBuilderFactoryBean bean = new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 			bean.setBasePath("/spring"); | ||||||
|  | 			return bean; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
| 			return http | 			return http | ||||||
| 					.authorizeHttpRequests((authorize) -> authorize | 					.authorizeHttpRequests((authorize) -> authorize | ||||||
| 						.requestMatchers(builder.basePath("/spring").matcher("/")).hasRole("ADMIN") | 						.requestMatchers(builder.matcher("/")).hasRole("ADMIN") | ||||||
| 					) | 					) | ||||||
| 					.build(); | 					.build(); | ||||||
| 			// @formatter:on | 			// @formatter:on | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ import org.springframework.mock.web.MockHttpServletResponse; | ||||||
| import org.springframework.mock.web.MockServletContext; | import org.springframework.mock.web.MockServletContext; | ||||||
| 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.web.PathPatternRequestMatcherBuilderFactoryBean; | ||||||
| import org.springframework.security.core.userdetails.UserDetailsService; | import org.springframework.security.core.userdetails.UserDetailsService; | ||||||
| import org.springframework.security.provisioning.InMemoryUserDetailsManager; | import org.springframework.security.provisioning.InMemoryUserDetailsManager; | ||||||
| import org.springframework.security.web.FilterChainProxy; | import org.springframework.security.web.FilterChainProxy; | ||||||
|  | @ -157,6 +158,11 @@ public class HttpSecurityRequestMatchersTests { | ||||||
| 	@EnableWebMvc | 	@EnableWebMvc | ||||||
| 	static class MultiMvcMatcherInLambdaConfig { | 	static class MultiMvcMatcherInLambdaConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			return new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		@Order(Ordered.HIGHEST_PRECEDENCE) | 		@Order(Ordered.HIGHEST_PRECEDENCE) | ||||||
| 		SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
|  | @ -204,6 +210,11 @@ public class HttpSecurityRequestMatchersTests { | ||||||
| 	@EnableWebMvc | 	@EnableWebMvc | ||||||
| 	static class MultiMvcMatcherConfig { | 	static class MultiMvcMatcherConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			return new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		@Order(Ordered.HIGHEST_PRECEDENCE) | 		@Order(Ordered.HIGHEST_PRECEDENCE) | ||||||
| 		SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
|  | @ -249,6 +260,11 @@ public class HttpSecurityRequestMatchersTests { | ||||||
| 	@EnableWebMvc | 	@EnableWebMvc | ||||||
| 	static class MvcMatcherConfig { | 	static class MvcMatcherConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			return new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
|  | @ -283,6 +299,11 @@ public class HttpSecurityRequestMatchersTests { | ||||||
| 	@EnableWebMvc | 	@EnableWebMvc | ||||||
| 	static class RequestMatchersMvcMatcherConfig { | 	static class RequestMatchersMvcMatcherConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			return new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
|  | @ -318,6 +339,11 @@ public class HttpSecurityRequestMatchersTests { | ||||||
| 	@EnableWebMvc | 	@EnableWebMvc | ||||||
| 	static class RequestMatchersMvcMatcherInLambdaConfig { | 	static class RequestMatchersMvcMatcherInLambdaConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			return new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
|  | @ -350,6 +376,11 @@ public class HttpSecurityRequestMatchersTests { | ||||||
| 	@EnableWebMvc | 	@EnableWebMvc | ||||||
| 	static class RequestMatchersMvcMatcherServeltPathConfig { | 	static class RequestMatchersMvcMatcherServeltPathConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			return new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
|  | @ -386,6 +417,11 @@ public class HttpSecurityRequestMatchersTests { | ||||||
| 	@EnableWebMvc | 	@EnableWebMvc | ||||||
| 	static class RequestMatchersMvcMatcherServletPathInLambdaConfig { | 	static class RequestMatchersMvcMatcherServletPathInLambdaConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			return new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ import org.springframework.mock.web.MockHttpServletRequest; | ||||||
| import org.springframework.mock.web.MockHttpServletResponse; | import org.springframework.mock.web.MockHttpServletResponse; | ||||||
| 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.web.PathPatternRequestMatcherBuilderFactoryBean; | ||||||
| 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; | ||||||
| import org.springframework.security.core.userdetails.UserDetailsService; | import org.springframework.security.core.userdetails.UserDetailsService; | ||||||
|  | @ -354,14 +355,20 @@ public class HttpSecuritySecurityMatchersTests { | ||||||
| 	@Import(UsersConfig.class) | 	@Import(UsersConfig.class) | ||||||
| 	static class SecurityMatchersMvcMatcherServletPathConfig { | 	static class SecurityMatchersMvcMatcherServletPathConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			PathPatternRequestMatcherBuilderFactoryBean bean = new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 			bean.setBasePath("/spring"); | ||||||
|  | 			return bean; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			PathPatternRequestMatcher.Builder spring = builder.basePath("/spring"); |  | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
| 			http | 			http | ||||||
| 				.securityMatchers((security) -> security | 				.securityMatchers((security) -> security | ||||||
| 					.requestMatchers(spring.matcher("/path")) | 					.requestMatchers(builder.matcher("/path")) | ||||||
| 					.requestMatchers(spring.matcher("/never-match")) | 					.requestMatchers(builder.matcher("/never-match")) | ||||||
| 				) | 				) | ||||||
| 				.httpBasic(withDefaults()) | 				.httpBasic(withDefaults()) | ||||||
| 				.authorizeHttpRequests((authorize) -> authorize | 				.authorizeHttpRequests((authorize) -> authorize | ||||||
|  | @ -388,14 +395,20 @@ public class HttpSecuritySecurityMatchersTests { | ||||||
| 	@Import(UsersConfig.class) | 	@Import(UsersConfig.class) | ||||||
| 	static class SecurityMatchersMvcMatcherServletPathInLambdaConfig { | 	static class SecurityMatchersMvcMatcherServletPathInLambdaConfig { | ||||||
| 
 | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { | ||||||
|  | 			PathPatternRequestMatcherBuilderFactoryBean bean = new PathPatternRequestMatcherBuilderFactoryBean(); | ||||||
|  | 			bean.setBasePath("/spring"); | ||||||
|  | 			return bean; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Bean | 		@Bean | ||||||
| 		SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | 		SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { | ||||||
| 			PathPatternRequestMatcher.Builder spring = builder.basePath("/spring"); |  | ||||||
| 			// @formatter:off | 			// @formatter:off | ||||||
| 			http | 			http | ||||||
| 				.securityMatchers((matchers) -> matchers | 				.securityMatchers((matchers) -> matchers | ||||||
| 					.requestMatchers(spring.matcher("/path")) | 					.requestMatchers(builder.matcher("/path")) | ||||||
| 					.requestMatchers(spring.matcher("/never-match")) | 					.requestMatchers(builder.matcher("/never-match")) | ||||||
| 				) | 				) | ||||||
| 				.httpBasic(withDefaults()) | 				.httpBasic(withDefaults()) | ||||||
| 				.authorizeHttpRequests((authorize) -> authorize | 				.authorizeHttpRequests((authorize) -> authorize | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue