From 3e53cc2c4ac1fb88231d415a568e738088a954b0 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Wed, 2 Jul 2025 17:49:50 -0600 Subject: [PATCH] Use PathPatternRequestMatcher in config This commit changes the config module to use PathPatternRequestMatcher in favor of MvcRequestMatcher and AntPathRequestMatcher. This allows removing several HandlerMappingIntrospector support classes as well which were in place to support MvcRequestMatcher. Issue gh-16886 Issue gh-16887 --- .../web/AbstractRequestMatcherRegistry.java | 341 +----------------- .../annotation/web/RequestMatcherFactory.java | 59 --- .../annotation/web/builders/HttpSecurity.java | 62 +--- .../annotation/web/builders/WebSecurity.java | 3 +- .../HttpSecurityConfiguration.java | 2 - .../WebMvcSecurityConfiguration.java | 95 ----- .../WebSecurityConfiguration.java | 16 +- .../configurers/AbstractHttpConfigurer.java | 12 + .../web/configurers/CorsConfigurer.java | 17 +- .../web/configurers/FormLoginConfigurer.java | 3 +- .../web/configurers/LogoutConfigurer.java | 5 +- .../PasswordManagementConfigurer.java | 3 +- .../configurers/RequestCacheConfigurer.java | 11 +- .../ott/OneTimeTokenLoginConfigurer.java | 12 +- ...bMvcSecurityConfigurationRuntimeHints.java | 4 - .../http/AuthorizationFilterParser.java | 2 +- .../config/http/CorsBeanDefinitionParser.java | 15 +- ...> CorsConfigurationSourceFactoryBean.java} | 17 +- .../http/DefaultFilterChainValidator.java | 15 +- ...nvocationSecurityMetadataSourceParser.java | 2 +- .../config/http/HttpConfigurationBuilder.java | 30 +- .../security/config/http/MatcherType.java | 38 +- .../PathPatternRequestMatcherFactoryBean.java | 77 ++++ .../http/RequestMatcherFactoryBean.java | 8 +- .../web/AbstractRequestMatcherDsl.kt | 2 +- .../web/AuthorizeHttpRequestsDsl.kt | 27 +- .../annotation/web/AuthorizeRequestsDsl.kt | 28 +- .../config/annotation/web/HttpSecurityDsl.kt | 3 +- .../annotation/web/RequiresChannelDsl.kt | 27 +- .../security/config/spring-security-7.0.rnc | 2 +- .../security/config/spring-security-7.0.xsd | 4 +- .../config/FilterChainProxyConfigTests.java | 3 +- .../annotation/issue50/SecurityConfig.java | 5 +- ...RequestMatcherRegistryAnyMatcherTests.java | 13 +- ...tractRequestMatcherRegistryNoMvcTests.java | 17 +- .../AbstractRequestMatcherRegistryTests.java | 270 +------------- .../web/builders/HttpConfigurationTests.java | 6 +- .../web/builders/NamespaceHttpTests.java | 24 +- .../WebSecurityFilterChainValidatorTests.java | 22 +- .../web/builders/WebSecurityTests.java | 14 +- ...vocationPrivilegeEvaluatorConfigTests.java | 32 +- ...ingIntrospectorCacheFilterConfigTests.java | 127 ------- .../WebSecurityConfigurationTests.java | 64 ++-- ...gAttributeRequestMatcherRegistryTests.java | 16 +- .../AuthorizeHttpRequestsConfigurerTests.java | 20 +- .../configurers/AuthorizeRequestsTests.java | 36 +- ...onfigurerIgnoringRequestMatchersTests.java | 10 +- .../web/configurers/CsrfConfigurerTests.java | 4 +- .../web/configurers/DefaultFiltersTests.java | 3 +- ...ingConfigurerAccessDeniedHandlerTests.java | 8 +- .../HttpSecurityRequestMatchersTests.java | 55 ++- ...ttpSecuritySecurityMatchersNoMvcTests.java | 4 +- .../HttpSecuritySecurityMatchersTests.java | 21 +- .../HttpsRedirectConfigurerTests.java | 5 - .../configurers/NamespaceRememberMeTests.java | 3 +- .../RequestCacheConfigurerTests.java | 6 - .../RequestMatcherConfigurerTests.java | 10 +- .../UrlAuthorizationConfigurerTests.java | 14 +- ...ecurityConfigurationRuntimeHintsTests.java | 8 - .../DefaultFilterChainValidatorTests.java | 11 +- ...tadataSourceBeanDefinitionParserTests.java | 13 +- .../config/http/FormLoginConfigTests.java | 2 +- .../config/http/InterceptUrlConfigTests.java | 65 ---- .../customconfigurer/CustomConfigurer.java | 5 +- .../config/annotation/web/CsrfDslTests.kt | 16 +- .../web/ExceptionHandlingDslTests.kt | 12 +- .../config/annotation/web/LogoutDslTests.kt | 9 +- .../annotation/web/RememberMeDslTests.kt | 3 +- .../HttpStrictTransportSecurityDslTests.kt | 4 +- ...erDataValueProcessorOnyIfNotRegistered.xml | 16 +- .../http/CsrfConfigTests-CsrfEnabled.xml | 1 - ...rmLoginConfigTests-WithRequestMatcher.xml} | 2 +- ...figTests-WithSuccessAndFailureHandlers.xml | 2 +- ...rceptUrlWhenRequestMatcherRefThenWorks.xml | 10 +- ...izationManagerFilterAllDispatcherTypes.xml | 8 +- ...tUrlConfigTests-CamelCasePathVariables.xml | 1 - ...lCasePathVariablesAuthorizationManager.xml | 1 - ...lConfigTests-DefaultMatcherServletPath.xml | 1 - ...MatcherServletPathAuthorizationManager.xml | 1 - ...figTests-FilterAllDispatcherTypesFalse.xml | 8 +- .../InterceptUrlConfigTests-PatchMethod.xml | 1 - ...gTests-PatchMethodAuthorizationManager.xml | 1 - .../InterceptUrlConfigTests-PathVariables.xml | 1 - ...ests-PathVariablesAuthorizationManager.xml | 1 - .../http/InterceptUrlConfigTests-Sec2256.xml | 1 - ...onfigTests-Sec2256AuthorizationManager.xml | 1 - ...onfigTests-TypeConversionPathVariables.xml | 1 - ...rsionPathVariablesAuthorizationManager.xml | 1 - .../MiscHttpConfigTests-AnonymousDisabled.xml | 1 - ...MiscHttpConfigTests-AnonymousEndpoints.xml | 1 - ...nfigTests-CustomHttpBasicEntryPointRef.xml | 1 - ...scHttpConfigTests-CustomRequestMatcher.xml | 2 +- ...scHttpConfigTests-NoSecurityForPattern.xml | 1 - .../MiscHttpConfigTests-OncePerRequest.xml | 1 - ...MiscHttpConfigTests-OncePerRequestTrue.xml | 1 - ...MiscHttpConfigTests-ProtectedLoginPage.xml | 1 - ...ProtectedLoginPageAuthorizationManager.xml | 1 - ...pBlockConfigTests-DistinctHttpElements.xml | 1 - ...Tests-IdenticallyPatternedHttpElements.xml | 1 - .../MultiHttpBlockConfigTests-Sec1937.xml | 1 - ...olderAndELConfigTests-AccessDeniedPage.xml | 1 - ...ELConfigTests-AccessDeniedPageWithSpEL.xml | 1 - ...ELConfigTests-InterceptUrlAndFormLogin.xml | 1 - ...Tests-InterceptUrlAndFormLoginWithSpEL.xml | 1 - ...laceHolderAndELConfigTests-PortMapping.xml | 1 - ...HolderAndELConfigTests-RequiresChannel.xml | 1 - ...olderAndELConfigTests-UnsecuredPattern.xml | 1 - .../RememberMeConfigTests-DefaultConfig.xml | 1 - ...berMeConfigTests-NegativeTokenValidity.xml | 1 - .../http/RememberMeConfigTests-Sec1827.xml | 1 - .../http/RememberMeConfigTests-Sec2165.xml | 1 - .../http/RememberMeConfigTests-Sec742.xml | 1 - .../RememberMeConfigTests-SecureCookie.xml | 1 - .../RememberMeConfigTests-TokenValidity.xml | 1 - ...Tests-WithAuthenticationSuccessHandler.xml | 1 - .../RememberMeConfigTests-WithDataSource.xml | 1 - ...mberMeConfigTests-WithRememberMeCookie.xml | 1 - ...rMeConfigTests-WithRememberMeParameter.xml | 1 - ...ests-WithSecurityContextHolderStrategy.xml | 1 - .../RememberMeConfigTests-WithServicesRef.xml | 1 - ...emberMeConfigTests-WithTokenRepository.xml | 1 - ...erMeConfigTests-WithUserDetailsService.xml | 1 - ...olderAwareRequestConfigTests-MultiHttp.xml | 3 +- ...entConfigTests-CreateSessionIfRequired.xml | 1 - ...nagementConfigTests-CreateSessionNever.xml | 1 - ...mentConfigTests-CreateSessionStateless.xml | 1 - ...tConfigTests-NoSessionManagementFilter.xml | 1 - .../SessionManagementConfigTests-Sec1208.xml | 1 - .../SessionManagementConfigTests-Sec2137.xml | 1 - ...Tests-SessionAuthenticationStrategyRef.xml | 1 - ...essionFixationProtectionMigrateSession.xml | 1 - ...figTests-SessionFixationProtectionNone.xml | 1 - ...ionProtectionNoneWithInvalidSessionUrl.xml | 1 - .../http/handlermappingintrospector.xml | 29 -- .../security/util/filtertest-valid.xml | 10 +- .../security/web/FilterChainProxy.java | 5 +- ...ilterInvocationSecurityMetadataSource.java | 12 +- 137 files changed, 495 insertions(+), 1570 deletions(-) delete mode 100644 config/src/main/java/org/springframework/security/config/annotation/web/RequestMatcherFactory.java rename config/src/main/java/org/springframework/security/config/http/{HandlerMappingIntrospectorFactoryBean.java => CorsConfigurationSourceFactoryBean.java} (76%) create mode 100644 config/src/main/java/org/springframework/security/config/http/PathPatternRequestMatcherFactoryBean.java delete mode 100644 config/src/test/java/org/springframework/security/config/annotation/web/configuration/HandlerMappingIntrospectorCacheFilterConfigTests.java rename config/src/test/resources/org/springframework/security/config/http/{FormLoginConfigTests-WithAntRequestMatcher.xml => FormLoginConfigTests-WithRequestMatcher.xml} (92%) delete mode 100644 config/src/test/resources/org/springframework/security/config/http/handlermappingintrospector.xml diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java index ba0a291653..f80dfd6cf7 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java @@ -18,41 +18,20 @@ package org.springframework.security.config.annotation.web; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; import jakarta.servlet.DispatcherType; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletRegistration; -import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.ApplicationContext; -import org.springframework.core.ResolvableType; import org.springframework.http.HttpMethod; import org.springframework.lang.Nullable; -import org.springframework.security.config.ObjectPostProcessor; -import org.springframework.security.config.annotation.web.ServletRegistrationsSupport.RegistrationMapping; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher; -import org.springframework.security.web.util.matcher.OrRequestMatcher; -import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; /** * A base class for registering {@link RequestMatcher}'s. For example, it might allow for @@ -65,23 +44,12 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector; */ public abstract class AbstractRequestMatcherRegistry { - private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; - - private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; - - private static final boolean mvcPresent; - private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE; private ApplicationContext context; private boolean anyRequestConfigured = false; - static { - mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, - AbstractRequestMatcherRegistry.class.getClassLoader()); - } - private final Log logger = LogFactory.getLog(getClass()); protected final void setApplicationContext(ApplicationContext context) { @@ -107,40 +75,6 @@ public abstract class AbstractRequestMatcherRegistry { return configurer; } - /** - * Creates {@link MvcRequestMatcher} instances for the method and patterns passed in - * @param method the HTTP method to use or null if any should be used - * @param mvcPatterns the Spring MVC patterns to match on - * @return a List of {@link MvcRequestMatcher} instances - * @deprecated Please use - * {@link org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.Builder} - * instead - */ - @Deprecated - protected final List createMvcMatchers(HttpMethod method, String... mvcPatterns) { - Assert.state(!this.anyRequestConfigured, "Can't configure mvcMatchers after anyRequest"); - ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class, Object.class); - ObjectProvider> postProcessors = this.context.getBeanProvider(type); - ObjectPostProcessor opp = postProcessors.getObject(); - if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { - throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME - + " of type " + HandlerMappingIntrospector.class.getName() - + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); - } - HandlerMappingIntrospector introspector = this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, - HandlerMappingIntrospector.class); - List matchers = new ArrayList<>(mvcPatterns.length); - for (String mvcPattern : mvcPatterns) { - MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern); - opp.postProcess(matcher); - if (method != null) { - matcher.setMethod(method); - } - matchers.add(matcher); - } - return matchers; - } - /** * Maps a {@link List} of * {@link org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher} @@ -184,12 +118,9 @@ public abstract class AbstractRequestMatcherRegistry { /** *

- * If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an - * {@link MvcRequestMatcher} that also specifies a specific {@link HttpMethod} to - * match on. This matcher will use the same rules that Spring MVC uses for matching. - * For example, often times a mapping of the path "/path" will match on "/path", - * "/path/", "/path.html", etc. If the {@link HandlerMappingIntrospector} is not - * available, maps to an {@link AntPathRequestMatcher}. + * Match when the {@link HttpMethod} is {@code method} and when the request URI + * matches one of {@code patterns}. See + * {@link org.springframework.web.util.pattern.PathPattern} for matching rules. *

*

* If a specific {@link RequestMatcher} must be specified, use @@ -197,8 +128,7 @@ public abstract class AbstractRequestMatcherRegistry { *

* @param method the {@link HttpMethod} to use or {@code null} for any * {@link HttpMethod}. - * @param patterns the patterns to match on. The rules for matching are defined by - * Spring MVC if {@link MvcRequestMatcher} is used + * @param patterns the patterns to match on * @return the object that is chained after creating the {@link RequestMatcher}. * @since 5.8 */ @@ -209,27 +139,11 @@ public abstract class AbstractRequestMatcherRegistry { + "leading slash in all your request matcher patterns. In future versions of " + "Spring Security, leaving out the leading slash will result in an exception."); } - if (!mvcPresent) { - return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns)); - } - if (!(this.context instanceof WebApplicationContext)) { - return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns)); - } - WebApplicationContext context = (WebApplicationContext) this.context; - ServletContext servletContext = context.getServletContext(); - if (servletContext == null) { - return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns)); - } + Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest"); + PathPatternRequestMatcher.Builder builder = this.context.getBean(PathPatternRequestMatcher.Builder.class); List matchers = new ArrayList<>(); for (String pattern : patterns) { - if (RequestMatcherFactory.usesPathPatterns()) { - matchers.add(RequestMatcherFactory.matcher(method, pattern)); - } - else { - AntPathRequestMatcher ant = new AntPathRequestMatcher(pattern, (method != null) ? method.name() : null); - MvcRequestMatcher mvc = createMvcMatchers(method, pattern).get(0); - matchers.add(new DeferredRequestMatcher((c) -> resolve(ant, mvc, c), mvc, ant)); - } + matchers.add(builder.matcher(method, pattern)); } return requestMatchers(matchers.toArray(new RequestMatcher[0])); } @@ -243,64 +157,16 @@ public abstract class AbstractRequestMatcherRegistry { return false; } - private RequestMatcher resolve(AntPathRequestMatcher ant, MvcRequestMatcher mvc, ServletContext servletContext) { - ServletRegistrationsSupport registrations = new ServletRegistrationsSupport(servletContext); - Collection mappings = registrations.mappings(); - if (mappings.isEmpty()) { - return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher()); - } - Collection dispatcherServletMappings = registrations.dispatcherServletMappings(); - if (dispatcherServletMappings.isEmpty()) { - return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher()); - } - if (dispatcherServletMappings.size() > 1) { - String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values()); - throw new IllegalArgumentException(errorMessage); - } - RegistrationMapping dispatcherServlet = dispatcherServletMappings.iterator().next(); - if (mappings.size() > 1 && !dispatcherServlet.isDefault()) { - String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values()); - throw new IllegalArgumentException(errorMessage); - } - if (dispatcherServlet.isDefault()) { - if (mappings.size() == 1) { - return mvc; - } - return new DispatcherServletDelegatingRequestMatcher(ant, mvc); - } - return mvc; - } - - private static String computeErrorMessage(Collection registrations) { - String template = """ - This method cannot decide whether these patterns are Spring MVC patterns or not. \ - This is because there is more than one mappable servlet in your servlet context: %s. - - To address this, please create one PathPatternRequestMatcher.Builder#servletPath for each servlet that has \ - authorized endpoints and use them to construct request matchers manually. - """; - Map> mappings = new LinkedHashMap<>(); - for (ServletRegistration registration : registrations) { - mappings.put(registration.getClassName(), registration.getMappings()); - } - return String.format(template, mappings); - } - /** *

- * If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an - * {@link MvcRequestMatcher} that does not care which {@link HttpMethod} is used. This - * matcher will use the same rules that Spring MVC uses for matching. For example, - * often times a mapping of the path "/path" will match on "/path", "/path/", - * "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps - * to an {@link AntPathRequestMatcher}. + * Match when the request URI matches one of {@code patterns}. See + * {@link org.springframework.web.util.pattern.PathPattern} for matching rules. *

*

* If a specific {@link RequestMatcher} must be specified, use * {@link #requestMatchers(RequestMatcher...)} instead *

- * @param patterns the patterns to match on. The rules for matching are defined by - * Spring MVC if {@link MvcRequestMatcher} is used + * @param patterns the patterns to match on * @return the object that is chained after creating the {@link RequestMatcher}. * @since 5.8 */ @@ -310,12 +176,7 @@ public abstract class AbstractRequestMatcherRegistry { /** *

- * If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an - * {@link MvcRequestMatcher} that matches on a specific {@link HttpMethod}. This - * matcher will use the same rules that Spring MVC uses for matching. For example, - * often times a mapping of the path "/path" will match on "/path", "/path/", - * "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps - * to an {@link AntPathRequestMatcher}. + * Match when the {@link HttpMethod} is {@code method} *

*

* If a specific {@link RequestMatcher} must be specified, use @@ -339,182 +200,4 @@ public abstract class AbstractRequestMatcherRegistry { */ protected abstract C chainRequestMatchers(List requestMatchers); - /** - * Utilities for creating {@link RequestMatcher} instances. - * - * @author Rob Winch - * @since 3.2 - */ - private static final class RequestMatchers { - - private RequestMatchers() { - } - - /** - * Create a {@link List} of {@link AntPathRequestMatcher} instances. - * @param httpMethod the {@link HttpMethod} to use or {@code null} for any - * {@link HttpMethod}. - * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} - * from - * @return a {@link List} of {@link AntPathRequestMatcher} instances - */ - static List antMatchers(HttpMethod httpMethod, String... antPatterns) { - return Arrays.asList(antMatchersAsArray(httpMethod, antPatterns)); - } - - /** - * Create a {@link List} of {@link AntPathRequestMatcher} instances that do not - * specify an {@link HttpMethod}. - * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} - * from - * @return a {@link List} of {@link AntPathRequestMatcher} instances - */ - static List antMatchers(String... antPatterns) { - return antMatchers(null, antPatterns); - } - - static RequestMatcher[] antMatchersAsArray(HttpMethod httpMethod, String... antPatterns) { - String method = (httpMethod != null) ? httpMethod.toString() : null; - RequestMatcher[] matchers = new RequestMatcher[antPatterns.length]; - for (int index = 0; index < antPatterns.length; index++) { - matchers[index] = new AntPathRequestMatcher(antPatterns[index], method); - } - return matchers; - } - - /** - * Create a {@link List} of {@link RegexRequestMatcher} instances. - * @param httpMethod the {@link HttpMethod} to use or {@code null} for any - * {@link HttpMethod}. - * @param regexPatterns the regular expressions to create - * {@link RegexRequestMatcher} from - * @return a {@link List} of {@link RegexRequestMatcher} instances - */ - static List regexMatchers(HttpMethod httpMethod, String... regexPatterns) { - String method = (httpMethod != null) ? httpMethod.toString() : null; - List matchers = new ArrayList<>(); - for (String pattern : regexPatterns) { - matchers.add(new RegexRequestMatcher(pattern, method)); - } - return matchers; - } - - /** - * Create a {@link List} of {@link RegexRequestMatcher} instances that do not - * specify an {@link HttpMethod}. - * @param regexPatterns the regular expressions to create - * {@link RegexRequestMatcher} from - * @return a {@link List} of {@link RegexRequestMatcher} instances - */ - static List regexMatchers(String... regexPatterns) { - return regexMatchers(null, regexPatterns); - } - - } - - static class DeferredRequestMatcher implements RequestMatcher { - - final Function requestMatcherFactory; - - final AtomicReference description = new AtomicReference<>(); - - final Map requestMatchers = new ConcurrentHashMap<>(); - - DeferredRequestMatcher(Function resolver, RequestMatcher... candidates) { - this.requestMatcherFactory = (sc) -> this.requestMatchers.computeIfAbsent(sc, resolver); - this.description.set("Deferred " + Arrays.toString(candidates)); - } - - RequestMatcher requestMatcher(ServletContext servletContext) { - return this.requestMatcherFactory.apply(servletContext); - } - - @Override - public boolean matches(HttpServletRequest request) { - return this.requestMatcherFactory.apply(request.getServletContext()).matches(request); - } - - @Override - public MatchResult matcher(HttpServletRequest request) { - return this.requestMatcherFactory.apply(request.getServletContext()).matcher(request); - } - - @Override - public String toString() { - return this.description.get(); - } - - } - - static class MockMvcRequestMatcher implements RequestMatcher { - - @Override - public boolean matches(HttpServletRequest request) { - return request.getAttribute("org.springframework.test.web.servlet.MockMvc.MVC_RESULT_ATTRIBUTE") != null; - } - - } - - static class DispatcherServletRequestMatcher implements RequestMatcher { - - @Override - public boolean matches(HttpServletRequest request) { - String name = request.getHttpServletMapping().getServletName(); - ServletRegistration registration = request.getServletContext().getServletRegistration(name); - Assert.notNull(registration, - () -> computeErrorMessage(request.getServletContext().getServletRegistrations().values())); - try { - Class clazz = Class.forName(registration.getClassName()); - return DispatcherServlet.class.isAssignableFrom(clazz); - } - catch (ClassNotFoundException ex) { - return false; - } - } - - } - - static class DispatcherServletDelegatingRequestMatcher implements RequestMatcher { - - private final AntPathRequestMatcher ant; - - private final MvcRequestMatcher mvc; - - private final RequestMatcher dispatcherServlet; - - DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc) { - this(ant, mvc, new OrRequestMatcher(new MockMvcRequestMatcher(), new DispatcherServletRequestMatcher())); - } - - DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc, - RequestMatcher dispatcherServlet) { - this.ant = ant; - this.mvc = mvc; - this.dispatcherServlet = dispatcherServlet; - } - - RequestMatcher requestMatcher(HttpServletRequest request) { - if (this.dispatcherServlet.matches(request)) { - return this.mvc; - } - return this.ant; - } - - @Override - public boolean matches(HttpServletRequest request) { - return requestMatcher(request).matches(request); - } - - @Override - public MatchResult matcher(HttpServletRequest request) { - return requestMatcher(request).matcher(request); - } - - @Override - public String toString() { - return "DispatcherServletDelegating [" + "ant = " + this.ant + ", mvc = " + this.mvc + "]"; - } - - } - } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/RequestMatcherFactory.java b/config/src/main/java/org/springframework/security/config/annotation/web/RequestMatcherFactory.java deleted file mode 100644 index e6cca45bf1..0000000000 --- a/config/src/main/java/org/springframework/security/config/annotation/web/RequestMatcherFactory.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2002-2025 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; - -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpMethod; -import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import org.springframework.security.web.util.matcher.RequestMatcher; - -/** - * This utility exists only to facilitate applications opting into using path patterns in - * the HttpSecurity DSL. It is for internal use only. - * - * @deprecated - */ -@Deprecated(forRemoval = true) -public final class RequestMatcherFactory { - - private static PathPatternRequestMatcher.Builder builder; - - public static void setApplicationContext(ApplicationContext context) { - builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class).getIfUnique(); - } - - public static boolean usesPathPatterns() { - return builder != null; - } - - public static RequestMatcher matcher(String path) { - return matcher(null, path); - } - - public static RequestMatcher matcher(HttpMethod method, String path) { - if (builder != null) { - return builder.matcher(method, path); - } - return new AntPathRequestMatcher(path, (method != null) ? method.name() : null); - } - - private RequestMatcherFactory() { - - } - -} diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java index bdd611fd27..aefc23911b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java @@ -28,7 +28,6 @@ import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.ApplicationContext; import org.springframework.core.OrderComparator; @@ -45,7 +44,6 @@ import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; -import org.springframework.security.config.annotation.web.RequestMatcherFactory; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; import org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer; @@ -91,17 +89,14 @@ import org.springframework.security.web.PortMapperImpl; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; import org.springframework.security.web.context.SecurityContextRepository; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.session.HttpSessionEventPublisher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.filter.CorsFilter; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; /** * A {@link HttpSecurity} is similar to Spring Security's XML <http> element in the @@ -153,12 +148,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector; public final class HttpSecurity extends AbstractConfiguredSecurityBuilder implements SecurityBuilder, HttpSecurityBuilder { - private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; - - private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; - - private static final boolean mvcPresent; - private final RequestMatcherConfigurer requestMatcherConfigurer; private List filters = new ArrayList<>(); @@ -169,10 +158,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder * @Configuration @@ -2174,7 +2157,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder * @param requestMatcher the {@link RequestMatcher} to use, for example, - * {@code PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/admin/**")} + * {@code PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/admin/**")} * @return the {@link HttpSecurity} for further customizations * @see #securityMatcher(String...) */ @@ -2185,10 +2168,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder * Invoking {@link #securityMatcher(String...)} will override previous invocations of @@ -2198,19 +2179,14 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder * @param patterns the pattern to match on (i.e. "/admin/**") * @return the {@link HttpSecurity} for further customizations - * @see AntPathRequestMatcher - * @see MvcRequestMatcher + * @see org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher + * @see org.springframework.web.util.pattern.PathPattern */ public HttpSecurity securityMatcher(String... patterns) { List matchers = new ArrayList<>(); + PathPatternRequestMatcher.Builder builder = getContext().getBean(PathPatternRequestMatcher.Builder.class); for (String pattern : patterns) { - if (RequestMatcherFactory.usesPathPatterns()) { - matchers.add(RequestMatcherFactory.matcher(pattern)); - } - else { - RequestMatcher matcher = mvcPresent ? createMvcMatcher(pattern) : createAntMatcher(pattern); - matchers.add(matcher); - } + matchers.add(builder.matcher(pattern)); } this.requestMatcher = new OrRequestMatcher(matchers); return this; @@ -2241,26 +2217,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder> postProcessors = getContext().getBeanProvider(type); - ObjectPostProcessor opp = postProcessors.getObject(); - if (!getContext().containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { - throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME - + " of type " + HandlerMappingIntrospector.class.getName() - + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); - } - HandlerMappingIntrospector introspector = getContext().getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, - HandlerMappingIntrospector.class); - MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern); - opp.postProcess(matcher); - return matcher; - } - /** * If the {@link SecurityConfigurer} has already been specified get the original, * otherwise apply the new {@link SecurityConfigurerAdapter}. diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java index 54c4566af8..1bb1def8d7 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java @@ -55,6 +55,7 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer; import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator; +import org.springframework.security.web.access.PathPatternRequestTransformer; import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; @@ -422,7 +423,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder requestTransformerClass = HttpServletRequestTransformer.class; this.privilegeEvaluatorRequestTransformer = applicationContext.getBeanProvider(requestTransformerClass) - .getIfUnique(); + .getIfUnique(PathPatternRequestTransformer::new); } @Override diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java index c139c7e10a..4593c84111 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java @@ -35,7 +35,6 @@ import org.springframework.security.config.annotation.authentication.configurati import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer; import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer; import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer; -import org.springframework.security.config.annotation.web.RequestMatcherFactory; 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.DefaultLoginPageConfigurer; @@ -105,7 +104,6 @@ class HttpSecurityConfiguration { @Bean(HTTPSECURITY_BEAN_NAME) @Scope("prototype") HttpSecurity httpSecurity() throws Exception { - RequestMatcherFactory.setApplicationContext(this.context); LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context); AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder( this.objectPostProcessor, passwordEncoder); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java index 73a56456d8..3e6459918c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java @@ -26,15 +26,7 @@ import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.BeansException; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.ManagedList; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; @@ -45,8 +37,6 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer; -import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; import org.springframework.security.web.debug.DebugFilter; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.RequestRejectedHandler; @@ -58,7 +48,6 @@ import org.springframework.web.filter.CompositeFilter; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import org.springframework.web.servlet.support.RequestDataValueProcessor; /** @@ -76,10 +65,6 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor; */ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContextAware { - private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; - - private static final String PATH_PATTERN_REQUEST_TRANSFORMER_BEAN_NAME = "pathPatternRequestTransformer"; - private BeanResolver beanResolver; private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder @@ -121,86 +106,6 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex } } - @Bean - static BeanDefinitionRegistryPostProcessor springSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor() { - return new BeanDefinitionRegistryPostProcessor() { - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - } - - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - if (!registry.containsBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { - return; - } - - String hmiRequestTransformerBeanName = HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + "RequestTransformer"; - if (!registry.containsBeanDefinition(PATH_PATTERN_REQUEST_TRANSFORMER_BEAN_NAME) - && !registry.containsBeanDefinition(hmiRequestTransformerBeanName)) { - if (!registry.containsBeanDefinition(hmiRequestTransformerBeanName)) { - BeanDefinition hmiRequestTransformer = BeanDefinitionBuilder - .rootBeanDefinition(HandlerMappingIntrospectorRequestTransformer.class) - .addConstructorArgReference(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME) - .getBeanDefinition(); - registry.registerBeanDefinition(hmiRequestTransformerBeanName, hmiRequestTransformer); - } - } - - BeanDefinition filterChainProxy = registry - .getBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME); - - if (!filterChainProxy.getResolvableType().isInstance(CompositeFilterChainProxy.class)) { - BeanDefinitionBuilder hmiCacheFilterBldr = BeanDefinitionBuilder - .rootBeanDefinition(HandlerMappingIntrospectorCacheFilterFactoryBean.class) - .setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - - ManagedList filters = new ManagedList<>(); - filters.add(hmiCacheFilterBldr.getBeanDefinition()); - filters.add(filterChainProxy); - BeanDefinitionBuilder compositeSpringSecurityFilterChainBldr = BeanDefinitionBuilder - .rootBeanDefinition(CompositeFilterChainProxy.class) - .addConstructorArgValue(filters); - - registry.removeBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME); - registry.registerBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, - compositeSpringSecurityFilterChainBldr.getBeanDefinition()); - } - } - }; - } - - /** - * {@link FactoryBean} to defer creation of - * {@link HandlerMappingIntrospector#createCacheFilter()} - * - * @deprecated see {@link WebSecurityConfiguration} for - * {@link org.springframework.web.util.pattern.PathPattern} replacement - */ - @Deprecated - static class HandlerMappingIntrospectorCacheFilterFactoryBean - implements ApplicationContextAware, FactoryBean { - - private ApplicationContext applicationContext; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - - @Override - public Filter getObject() throws Exception { - HandlerMappingIntrospector handlerMappingIntrospector = this.applicationContext - .getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class); - return handlerMappingIntrospector.createCacheFilter(); - } - - @Override - public Class getObjectType() { - return Filter.class; - } - - } - /** * Extends {@link FilterChainProxy} to provide as much passivity as possible but * delegates to {@link CompositeFilter} for diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java index 7e31a0ebf9..41bd042f75 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java @@ -42,6 +42,7 @@ import org.springframework.beans.factory.support.ManagedList; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Fallback; import org.springframework.context.annotation.ImportAware; import org.springframework.core.OrderComparator; import org.springframework.core.Ordered; @@ -57,6 +58,7 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.crypto.RsaKeyConversionServicePostProcessor; +import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; import org.springframework.security.context.DelegatingApplicationListener; import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.web.FilterChainProxy; @@ -69,7 +71,6 @@ import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.RequestRejectedHandler; import org.springframework.web.filter.CompositeFilter; import org.springframework.web.filter.ServletRequestPathFilter; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; /** * Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web @@ -143,6 +144,12 @@ public class WebSecurityConfiguration implements ImportAware { return this.webSecurity.getPrivilegeEvaluator(); } + @Bean + @Fallback + public PathPatternRequestMatcherBuilderFactoryBean pathPatternRequestMatcherBuilder() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + /** * Sets the {@code } * instances used to create the web configuration. @@ -209,12 +216,11 @@ public class WebSecurityConfiguration implements ImportAware { /** * Used to ensure Spring MVC request matching is cached. * - * Creates a {@link BeanDefinitionRegistryPostProcessor} that detects if a bean named - * HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME is defined. If so, it moves the + * Creates a {@link BeanDefinitionRegistryPostProcessor} that moves the * AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME to another bean name * and then adds a {@link CompositeFilter} that contains - * {@link HandlerMappingIntrospector#createCacheFilter()} and the original - * FilterChainProxy under the original Bean name. + * {@link ServletRequestPathFilter} and the original FilterChainProxy under the + * original Bean name. * @return */ @Bean diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java index d25d3575b1..46d261c1e4 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java @@ -25,6 +25,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; /** * Adds a convenient base class for {@link SecurityConfigurer} instances that operate on @@ -38,6 +39,8 @@ public abstract class AbstractHttpConfigurer the builder to return. * @author Rob Winch @@ -45,16 +41,8 @@ public class CorsConfigurer> extends AbstractHt private static final String CORS_FILTER_BEAN_NAME = "corsFilter"; - private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; - - private static final boolean mvcPresent; - private CorsConfigurationSource configurationSource; - static { - mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, CorsConfigurer.class.getClassLoader()); - } - /** * Creates a new instance * @@ -91,10 +79,7 @@ public class CorsConfigurer> extends AbstractHt CorsConfigurationSource.class); return new CorsFilter(configurationSource); } - if (mvcPresent) { - return MvcCorsFilter.getMvcCorsFilter(context); - } - return null; + return MvcCorsFilter.getMvcCorsFilter(context); } static class MvcCorsFilter { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java index b4a483ac3b..338a8d852b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java @@ -19,7 +19,6 @@ package org.springframework.security.config.annotation.web.configurers; import org.springframework.http.HttpMethod; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; -import org.springframework.security.config.annotation.web.RequestMatcherFactory; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.AuthenticationEntryPoint; @@ -236,7 +235,7 @@ public final class FormLoginConfigurer> extends @Override protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) { - return RequestMatcherFactory.matcher(HttpMethod.POST, loginProcessingUrl); + return getRequestMatcherBuilder().matcher(HttpMethod.POST, loginProcessingUrl); } /** diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java index fa9a8298a2..8f23ffa05c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java @@ -26,7 +26,6 @@ import org.springframework.http.HttpMethod; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.SecurityConfigurer; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; -import org.springframework.security.config.annotation.web.RequestMatcherFactory; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler; @@ -146,7 +145,7 @@ public final class LogoutConfigurer> * (i.e. log out) to protect against * CSRF * attacks. If you really want to use an HTTP GET, you can use - * logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GEt, logoutUrl)); + * logoutRequestMatcher(PathPatternRequestMatcher.pathPattern(HttpMethod.GEt, logoutUrl)); *

* @param logoutUrl the URL that will invoke logout. * @return the {@link LogoutConfigurer} for further customization @@ -370,7 +369,7 @@ public final class LogoutConfigurer> } private RequestMatcher createLogoutRequestMatcher(String httpMethod) { - return RequestMatcherFactory.matcher(HttpMethod.valueOf(httpMethod), this.logoutUrl); + return getRequestMatcherBuilder().matcher(HttpMethod.valueOf(httpMethod), this.logoutUrl); } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PasswordManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PasswordManagementConfigurer.java index 7d5794b826..d9a3e3e01c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PasswordManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PasswordManagementConfigurer.java @@ -17,7 +17,6 @@ package org.springframework.security.config.annotation.web.configurers; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; -import org.springframework.security.config.annotation.web.RequestMatcherFactory; import org.springframework.security.web.RequestMatcherRedirectFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.util.Assert; @@ -55,7 +54,7 @@ public final class PasswordManagementConfigurer @Override public void configure(B http) throws Exception { RequestMatcherRedirectFilter changePasswordFilter = new RequestMatcherRedirectFilter( - RequestMatcherFactory.matcher(WELL_KNOWN_CHANGE_PASSWORD_PATTERN), this.changePasswordPage); + getRequestMatcherBuilder().matcher(WELL_KNOWN_CHANGE_PASSWORD_PATTERN), this.changePasswordPage); http.addFilterBefore(postProcess(changePasswordFilter), UsernamePasswordAuthenticationFilter.class); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java index 3be334a17d..c986397bbb 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java @@ -24,14 +24,12 @@ import org.springframework.context.ApplicationContext; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; -import org.springframework.security.config.annotation.web.RequestMatcherFactory; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.NullRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.RequestCacheAwareFilter; import org.springframework.security.web.util.matcher.AndRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher; import org.springframework.security.web.util.matcher.NegatedRequestMatcher; import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher; @@ -151,7 +149,7 @@ public final class RequestCacheConfigurer> boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null; List matchers = new ArrayList<>(); if (isCsrfEnabled) { - RequestMatcher getRequests = RequestMatcherFactory.matcher(HttpMethod.GET, "/**"); + RequestMatcher getRequests = getRequestMatcherBuilder().matcher(HttpMethod.GET, "/**"); matchers.add(0, getRequests); } matchers.add(notFavIcon); @@ -174,12 +172,7 @@ public final class RequestCacheConfigurer> } private RequestMatcher getFaviconRequestMatcher() { - if (RequestMatcherFactory.usesPathPatterns()) { - return RequestMatcherFactory.matcher("/favicon.*"); - } - else { - return new AntPathRequestMatcher("/**/favicon.*"); - } + return getRequestMatcherBuilder().matcher("/favicon.*"); } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ott/OneTimeTokenLoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ott/OneTimeTokenLoginConfigurer.java index 7be52d83c1..457212c41e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ott/OneTimeTokenLoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ott/OneTimeTokenLoginConfigurer.java @@ -31,7 +31,6 @@ import org.springframework.security.authentication.ott.OneTimeTokenAuthenticatio import org.springframework.security.authentication.ott.OneTimeTokenService; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; -import org.springframework.security.config.annotation.web.RequestMatcherFactory; 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.configurers.AbstractAuthenticationFilterConfigurer; @@ -122,12 +121,15 @@ public final class OneTimeTokenLoginConfigurer> private GenerateOneTimeTokenRequestResolver requestResolver; public OneTimeTokenLoginConfigurer(ApplicationContext context) { - super(new OneTimeTokenAuthenticationFilter(), OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL); + super(new OneTimeTokenAuthenticationFilter(), null); this.context = context; } @Override public void init(H http) throws Exception { + if (getLoginProcessingUrl() == null) { + loginProcessingUrl(OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL); + } super.init(http); AuthenticationProvider authenticationProvider = getAuthenticationProvider(); http.authenticationProvider(postProcess(authenticationProvider)); @@ -162,7 +164,7 @@ public final class OneTimeTokenLoginConfigurer> private void configureOttGenerateFilter(H http) { GenerateOneTimeTokenFilter generateFilter = new GenerateOneTimeTokenFilter(getOneTimeTokenService(), getOneTimeTokenGenerationSuccessHandler()); - generateFilter.setRequestMatcher(RequestMatcherFactory.matcher(HttpMethod.POST, this.tokenGeneratingUrl)); + generateFilter.setRequestMatcher(getRequestMatcherBuilder().matcher(HttpMethod.POST, this.tokenGeneratingUrl)); generateFilter.setRequestResolver(getGenerateRequestResolver()); http.addFilter(postProcess(generateFilter)); http.addFilter(DefaultResourcesFilter.css()); @@ -189,7 +191,7 @@ public final class OneTimeTokenLoginConfigurer> } DefaultOneTimeTokenSubmitPageGeneratingFilter submitPage = new DefaultOneTimeTokenSubmitPageGeneratingFilter(); submitPage.setResolveHiddenInputs(this::hiddenInputs); - submitPage.setRequestMatcher(RequestMatcherFactory.matcher(HttpMethod.GET, this.defaultSubmitPageUrl)); + submitPage.setRequestMatcher(getRequestMatcherBuilder().matcher(HttpMethod.GET, this.defaultSubmitPageUrl)); submitPage.setLoginProcessingUrl(this.getLoginProcessingUrl()); http.addFilter(postProcess(submitPage)); } @@ -206,7 +208,7 @@ public final class OneTimeTokenLoginConfigurer> @Override protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) { - return RequestMatcherFactory.matcher(HttpMethod.POST, loginProcessingUrl); + return getRequestMatcherBuilder().matcher(HttpMethod.POST, loginProcessingUrl); } /** diff --git a/config/src/main/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHints.java b/config/src/main/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHints.java index 9d292b2477..18ff47e5ca 100644 --- a/config/src/main/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHints.java +++ b/config/src/main/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHints.java @@ -35,10 +35,6 @@ class WebMvcSecurityConfigurationRuntimeHints implements RuntimeHintsRegistrar { .registerType(TypeReference .of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy"), MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); - hints.reflection() - .registerType(TypeReference - .of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean"), - MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); } } diff --git a/config/src/main/java/org/springframework/security/config/http/AuthorizationFilterParser.java b/config/src/main/java/org/springframework/security/config/http/AuthorizationFilterParser.java index 53ff1238b0..dff1e58368 100644 --- a/config/src/main/java/org/springframework/security/config/http/AuthorizationFilterParser.java +++ b/config/src/main/java/org/springframework/security/config/http/AuthorizationFilterParser.java @@ -153,7 +153,7 @@ class AuthorizationFilterParser implements BeanDefinitionParser { if (!StringUtils.hasText(servletPath)) { servletPath = null; } - else if (!MatcherType.mvc.equals(matcherType)) { + else if (!MatcherType.path.equals(matcherType)) { parserContext.getReaderContext() .error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", urlElt); diff --git a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java index 94d8730062..6410f2f2fa 100644 --- a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java @@ -24,7 +24,6 @@ import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.web.filter.CorsFilter; @@ -40,15 +39,6 @@ public class CorsBeanDefinitionParser { private static final String ATT_REF = "ref"; - private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; - - private static final boolean mvcPresent; - - static { - mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, - CorsBeanDefinitionParser.class.getClassLoader()); - } - public BeanMetadataElement parse(Element element, ParserContext parserContext) { if (element == null) { return null; @@ -71,10 +61,7 @@ public class CorsBeanDefinitionParser { if (StringUtils.hasText(configurationSourceRef)) { return new RuntimeBeanReference(configurationSourceRef); } - if (!mvcPresent) { - return null; - } - return new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class); + return new RootBeanDefinition(CorsConfigurationSourceFactoryBean.class); } } diff --git a/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java b/config/src/main/java/org/springframework/security/config/http/CorsConfigurationSourceFactoryBean.java similarity index 76% rename from config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java rename to config/src/main/java/org/springframework/security/config/http/CorsConfigurationSourceFactoryBean.java index 302e95834a..60da7445cc 100644 --- a/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/http/CorsConfigurationSourceFactoryBean.java @@ -22,38 +22,37 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.lang.Nullable; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; +import org.springframework.web.cors.CorsConfigurationSource; /** - * Used for creating an instance of {@link HandlerMappingIntrospector} and autowiring the + * Used for creating an instance of {@link CorsConfigurationSource} and autowiring the * {@link ApplicationContext}. * * @author Rob Winch * @since 4.1.1 */ -class HandlerMappingIntrospectorFactoryBean - implements FactoryBean, ApplicationContextAware { +class CorsConfigurationSourceFactoryBean implements FactoryBean, ApplicationContextAware { private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; private ApplicationContext context; @Override - public HandlerMappingIntrospector getObject() { + public CorsConfigurationSource getObject() { if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type " - + HandlerMappingIntrospector.class.getName() - + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring " + + CorsConfigurationSource.class.getName() + + " is required to use . Please ensure Spring Security & Spring " + "MVC are configured in a shared ApplicationContext."); } - return this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class); + return this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, CorsConfigurationSource.class); } @Nullable @Override public Class getObjectType() { - return HandlerMappingIntrospector.class; + return CorsConfigurationSource.class; } @Override diff --git a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java index 8f2baeb4c6..84c9d65e97 100644 --- a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java +++ b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java @@ -40,7 +40,9 @@ import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.UnreachableFilterChainException; +import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.ExceptionTranslationFilter; +import org.springframework.security.web.access.PathPatternRequestTransformer; import org.springframework.security.web.access.intercept.AuthorizationFilter; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; @@ -61,6 +63,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain private final Log logger = LogFactory.getLog(getClass()); + private final AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer requestTransformer = new PathPatternRequestTransformer(); + @Override public void validate(FilterChainProxy fcp) { for (SecurityFilterChain filterChain : fcp.getFilterChains()) { @@ -188,7 +192,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain String loginPage = ((LoginUrlAuthenticationEntryPoint) exceptions.getAuthenticationEntryPoint()) .getLoginFormUrl(); this.logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration"); - FilterInvocation loginRequest = new FilterInvocation(loginPage, "POST"); + FilterInvocation invocation = new FilterInvocation(loginPage, "POST"); + HttpServletRequest loginRequest = this.requestTransformer.transform(invocation.getRequest()); List filters = null; try { filters = fcp.getFilters(loginPage); @@ -237,7 +242,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain } } - private boolean checkLoginPageIsPublic(List filters, FilterInvocation loginRequest) { + private boolean checkLoginPageIsPublic(List filters, HttpServletRequest loginRequest) { FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters); if (authorizationInterceptor != null) { FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource(); @@ -257,7 +262,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain AuthorizationManager authorizationManager = authorizationFilter .getAuthorizationManager(); try { - AuthorizationResult result = authorizationManager.authorize(() -> TEST, loginRequest.getHttpRequest()); + AuthorizationResult result = authorizationManager.authorize(() -> TEST, loginRequest); return result != null && result.isGranted(); } catch (Exception ex) { @@ -267,7 +272,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain return false; } - private Supplier deriveAnonymousCheck(List filters, FilterInvocation loginRequest, + private Supplier deriveAnonymousCheck(List filters, HttpServletRequest loginRequest, AnonymousAuthenticationToken token) { FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters); if (authorizationInterceptor != null) { @@ -288,7 +293,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain return () -> { AuthorizationManager authorizationManager = authorizationFilter .getAuthorizationManager(); - AuthorizationResult result = authorizationManager.authorize(() -> token, loginRequest.getHttpRequest()); + AuthorizationResult result = authorizationManager.authorize(() -> token, loginRequest); return result != null && result.isGranted(); }; } diff --git a/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java b/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java index 506aa3cd2b..19e0502f4f 100644 --- a/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java +++ b/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java @@ -159,7 +159,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit if (!StringUtils.hasText(servletPath)) { servletPath = null; } - else if (!MatcherType.mvc.equals(matcherType)) { + else if (!MatcherType.path.equals(matcherType)) { parserContext.getReaderContext() .error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", urlElt); diff --git a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java index 1b22c044f6..08f171254c 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java @@ -45,12 +45,12 @@ import org.springframework.security.access.vote.AuthenticatedVoter; import org.springframework.security.access.vote.RoleVoter; import org.springframework.security.config.Elements; import org.springframework.security.config.http.GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory; +import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator; -import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer; import org.springframework.security.web.access.PathPatternRequestTransformer; import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl; import org.springframework.security.web.access.channel.ChannelProcessingFilter; @@ -88,7 +88,6 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; /** * Stateful class which helps HttpSecurityBDP to create the configuration for the @@ -100,11 +99,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector; */ class HttpConfigurationBuilder { - private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; - - private static final boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, - HttpConfigurationBuilder.class.getClassLoader()); - private static final String ATT_CREATE_SESSION = "create-session"; private static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection"; @@ -165,6 +159,8 @@ class HttpConfigurationBuilder { private static final String DEF_JAAS_API_PROVISION = "false"; + private static final String REQUEST_MATCHER_BUILDER_BEAN_NAME = "HttpConfigurationBuilder-pathPatternRequestMatcherBuilder"; + private final Element httpElt; private final ParserContext pc; @@ -244,6 +240,13 @@ class HttpConfigurationBuilder { String createSession = element.getAttribute(ATT_CREATE_SESSION); this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED : createPolicy(createSession); + if (!this.pc.getRegistry().containsBeanDefinition(REQUEST_MATCHER_BUILDER_BEAN_NAME)) { + BeanDefinitionBuilder pathPatternRequestMatcherBuilder = BeanDefinitionBuilder + .rootBeanDefinition(PathPatternRequestMatcherBuilderFactoryBean.class); + pathPatternRequestMatcherBuilder.setFallback(true); + BeanDefinition bean = pathPatternRequestMatcherBuilder.getBeanDefinition(); + this.pc.registerBeanComponent(new BeanComponentDefinition(bean, REQUEST_MATCHER_BUILDER_BEAN_NAME)); + } createSecurityContextHolderStrategy(); createForceEagerSessionCreationFilter(); createDisableEncodeUrlFilter(); @@ -793,10 +796,8 @@ class HttpConfigurationBuilder { BeanDefinitionBuilder wipeBldr = BeanDefinitionBuilder .rootBeanDefinition(AuthorizationManagerWebInvocationPrivilegeEvaluator.class) .addConstructorArgReference(authorizationFilterParser.getAuthorizationManagerRef()); - if (mvcPresent) { - wipeBldr.addPropertyValue("requestTransformer", - new RootBeanDefinition(HandlerMappingIntrospectorRequestTransformerFactoryBean.class)); - } + wipeBldr.addPropertyValue("requestTransformer", + new RootBeanDefinition(PathPatternRequestTransformerFactoryBean.class)); BeanDefinition wipe = wipeBldr.getBeanDefinition(); this.pc.registerBeanComponent( new BeanComponentDefinition(wipe, this.pc.getReaderContext().generateBeanName(wipe))); @@ -966,7 +967,7 @@ class HttpConfigurationBuilder { return BeanDefinitionBuilder.rootBeanDefinition(ObservationRegistryFactory.class).getBeanDefinition(); } - static class HandlerMappingIntrospectorRequestTransformerFactoryBean + static class PathPatternRequestTransformerFactoryBean implements FactoryBean, ApplicationContextAware { @@ -982,10 +983,7 @@ class HttpConfigurationBuilder { if (requestTransformer != null) { return requestTransformer; } - HandlerMappingIntrospector hmi = this.applicationContext.getBeanProvider(HandlerMappingIntrospector.class) - .getIfAvailable(); - return (hmi != null) ? new HandlerMappingIntrospectorRequestTransformer(hmi) - : new PathPatternRequestTransformer(); + return new PathPatternRequestTransformer(); } @Override diff --git a/config/src/main/java/org/springframework/security/config/http/MatcherType.java b/config/src/main/java/org/springframework/security/config/http/MatcherType.java index 3755cb84e8..8a1dcb16cf 100644 --- a/config/src/main/java/org/springframework/security/config/http/MatcherType.java +++ b/config/src/main/java/org/springframework/security/config/http/MatcherType.java @@ -22,13 +22,12 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.http.HttpMethod; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; -import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** @@ -39,21 +38,13 @@ import org.springframework.util.StringUtils; */ public enum MatcherType { - ant(AntPathRequestMatcher.class), regex(RegexRequestMatcher.class), ciRegex(RegexRequestMatcher.class), - mvc(MvcRequestMatcher.class); - - private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; - - private static final boolean mvcPresent; + ant(AntPathRequestMatcher.class), path(PathPatternRequestMatcher.class), regex(RegexRequestMatcher.class), + ciRegex(RegexRequestMatcher.class), mvc(MvcRequestMatcher.class); private static final String ATT_MATCHER_TYPE = "request-matcher"; final Class type; - static { - mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, MatcherType.class.getClassLoader()); - } - MatcherType(Class type) { this.type = type; } @@ -66,18 +57,17 @@ public enum MatcherType { if (("/**".equals(path) || "**".equals(path)) && method == null) { return new RootBeanDefinition(AnyRequestMatcher.class); } - BeanDefinitionBuilder matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type); - if (this == mvc) { - matcherBldr.addConstructorArgValue(new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class)); - } - matcherBldr.addConstructorArgValue(path); - if (this == mvc) { - matcherBldr.addPropertyValue("method", (StringUtils.hasText(method) ? HttpMethod.valueOf(method) : null)); - matcherBldr.addPropertyValue("servletPath", servletPath); + BeanDefinitionBuilder matcherBldr; + if (this == MatcherType.path) { + matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(PathPatternRequestMatcherFactoryBean.class); + matcherBldr.addConstructorArgValue(path); + matcherBldr.addPropertyValue("basePath", servletPath); } else { - matcherBldr.addConstructorArgValue(method); + matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type); + matcherBldr.addConstructorArgValue(path); } + matcherBldr.addConstructorArgValue(method); if (this == ciRegex) { matcherBldr.addConstructorArgValue(true); } @@ -89,14 +79,10 @@ public enum MatcherType { return valueOf(elt.getAttribute(ATT_MATCHER_TYPE)); } - return ant; + return path; } static MatcherType fromElementOrMvc(Element elt) { - String matcherTypeName = elt.getAttribute(ATT_MATCHER_TYPE); - if (!StringUtils.hasText(matcherTypeName) && mvcPresent) { - return MatcherType.mvc; - } return MatcherType.fromElement(elt); } diff --git a/config/src/main/java/org/springframework/security/config/http/PathPatternRequestMatcherFactoryBean.java b/config/src/main/java/org/springframework/security/config/http/PathPatternRequestMatcherFactoryBean.java new file mode 100644 index 0000000000..7037bd2853 --- /dev/null +++ b/config/src/main/java/org/springframework/security/config/http/PathPatternRequestMatcherFactoryBean.java @@ -0,0 +1,77 @@ +/* + * Copyright 2002-2025 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.http; + +import org.jspecify.annotations.Nullable; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.http.HttpMethod; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; +import org.springframework.util.StringUtils; + +public final class PathPatternRequestMatcherFactoryBean + implements FactoryBean, ApplicationContextAware, InitializingBean { + + private final String pattern; + + private String basePath; + + private HttpMethod method; + + private PathPatternRequestMatcher.Builder builder; + + PathPatternRequestMatcherFactoryBean(String pattern) { + this.pattern = pattern; + } + + PathPatternRequestMatcherFactoryBean(String pattern, String method) { + this.pattern = pattern; + this.method = StringUtils.hasText(method) ? HttpMethod.valueOf(method) : null; + } + + @Override + public @Nullable PathPatternRequestMatcher getObject() throws Exception { + return this.builder.matcher(this.method, this.pattern); + } + + @Override + public @Nullable Class getObjectType() { + return PathPatternRequestMatcher.class; + } + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + this.builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class) + .getIfUnique(PathPatternRequestMatcher::withDefaults); + } + + @Override + public void afterPropertiesSet() throws Exception { + if (this.basePath != null) { + this.builder.basePath(this.basePath); + } + } + +} diff --git a/config/src/main/java/org/springframework/security/config/http/RequestMatcherFactoryBean.java b/config/src/main/java/org/springframework/security/config/http/RequestMatcherFactoryBean.java index f08a21727a..de3d7f9db8 100644 --- a/config/src/main/java/org/springframework/security/config/http/RequestMatcherFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/http/RequestMatcherFactoryBean.java @@ -22,7 +22,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.http.HttpMethod; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; @Deprecated @@ -45,10 +44,7 @@ public final class RequestMatcherFactoryBean implements FactoryBean) protected enum class PatternType { - ANT, MVC + ANT, MVC, PATH; } } diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt index 0133670a18..5488dd0289 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt @@ -31,11 +31,9 @@ import org.springframework.security.core.Authentication import org.springframework.security.web.access.IpAddressAuthorizationManager import org.springframework.security.web.access.intercept.AuthorizationFilter import org.springframework.security.web.access.intercept.RequestAuthorizationContext -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher import org.springframework.security.web.util.matcher.AnyRequestMatcher import org.springframework.security.web.util.matcher.RequestMatcher -import org.springframework.util.ClassUtils -import org.springframework.web.servlet.handler.HandlerMappingIntrospector import java.util.function.Supplier /** @@ -69,12 +67,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl { private val rolePrefix: String private val roleHierarchy: RoleHierarchy - private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector" - private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector" - private val MVC_PRESENT = ClassUtils.isPresent( - HANDLER_MAPPING_INTROSPECTOR, - AuthorizeHttpRequestsDsl::class.java.classLoader) - private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT + private val PATTERN_TYPE = PatternType.PATH /** * Adds a request authorization rule. @@ -288,17 +281,13 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl { when (rule) { is MatcherAuthorizationManagerRule -> requests.requestMatchers(rule.matcher).access(rule.rule) is PatternAuthorizationManagerRule -> { - when (rule.patternType) { - PatternType.ANT -> requests.requestMatchers(rule.httpMethod, rule.pattern).access(rule.rule) - PatternType.MVC -> { - val introspector = requests.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java) - val mvcMatcher = MvcRequestMatcher.Builder(introspector) - .servletPath(rule.servletPath) - .pattern(rule.pattern) - mvcMatcher.setMethod(rule.httpMethod) - requests.requestMatchers(mvcMatcher).access(rule.rule) - } + var builder = requests.applicationContext.getBeanProvider( + PathPatternRequestMatcher.Builder::class.java) + .getIfUnique(PathPatternRequestMatcher::withDefaults) + if (rule.servletPath != null) { + builder = builder.basePath(rule.servletPath) } + requests.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).access(rule.rule) } } } diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDsl.kt index f6891ca0ef..2620ccbe82 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDsl.kt @@ -19,11 +19,9 @@ package org.springframework.security.config.annotation.web import org.springframework.http.HttpMethod import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher import org.springframework.security.web.util.matcher.AnyRequestMatcher import org.springframework.security.web.util.matcher.RequestMatcher -import org.springframework.util.ClassUtils -import org.springframework.web.servlet.handler.HandlerMappingIntrospector /** * A Kotlin DSL to configure [HttpSecurity] request authorization using idiomatic Kotlin code. @@ -33,13 +31,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector */ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() { private val authorizationRules = mutableListOf() - - private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector" - private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector" - private val MVC_PRESENT = ClassUtils.isPresent( - HANDLER_MAPPING_INTROSPECTOR, - AuthorizeRequestsDsl::class.java.classLoader) - private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT + private val PATTERN_TYPE = PatternType.PATH; /** * Adds a request authorization rule. @@ -226,17 +218,13 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() { when (rule) { is MatcherAuthorizationRule -> requests.requestMatchers(rule.matcher).access(rule.rule) is PatternAuthorizationRule -> { - when (rule.patternType) { - PatternType.ANT -> requests.requestMatchers(rule.httpMethod, rule.pattern).access(rule.rule) - PatternType.MVC -> { - val introspector = requests.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java) - val mvcMatcher = MvcRequestMatcher.Builder(introspector) - .servletPath(rule.servletPath) - .pattern(rule.pattern) - mvcMatcher.setMethod(rule.httpMethod) - requests.requestMatchers(mvcMatcher).access(rule.rule) - } + var builder = requests.applicationContext.getBeanProvider( + PathPatternRequestMatcher.Builder::class.java) + .getIfUnique(PathPatternRequestMatcher::withDefaults); + if (rule.servletPath != null) { + builder = builder.basePath(rule.servletPath) } + requests.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).access(rule.rule) } } } diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/HttpSecurityDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/HttpSecurityDsl.kt index b1246a122a..9a62bd76f1 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/HttpSecurityDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/HttpSecurityDsl.kt @@ -73,7 +73,6 @@ operator fun HttpSecurity.invoke(httpConfiguration: HttpSecurityDsl.() -> Unit) */ @SecurityMarker class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecurityDsl.() -> Unit) { - private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector" var authenticationManager: AuthenticationManager? = null val context: ApplicationContext = http.getSharedObject(ApplicationContext::class.java) @@ -192,7 +191,7 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu * @Bean * fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { * http { - * securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/private/**")) + * securityMatcher(pathPattern("/private/**")) * formLogin { * loginPage = "/log-in" * } diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/RequiresChannelDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/RequiresChannelDsl.kt index e57aaf19a0..fe7f4e78de 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/RequiresChannelDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/RequiresChannelDsl.kt @@ -20,11 +20,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl import org.springframework.security.web.access.channel.ChannelProcessor -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher import org.springframework.security.web.util.matcher.AnyRequestMatcher import org.springframework.security.web.util.matcher.RequestMatcher -import org.springframework.util.ClassUtils -import org.springframework.web.servlet.handler.HandlerMappingIntrospector /** * A Kotlin DSL to configure [HttpSecurity] channel security using idiomatic @@ -38,12 +36,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector class RequiresChannelDsl : AbstractRequestMatcherDsl() { private val channelSecurityRules = mutableListOf() - private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector" - private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector" - private val MVC_PRESENT = ClassUtils.isPresent( - HANDLER_MAPPING_INTROSPECTOR, - RequiresChannelDsl::class.java.classLoader) - private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT + private val PATTERN_TYPE = PatternType.PATH var channelProcessors: List? = null @@ -121,17 +114,13 @@ class RequiresChannelDsl : AbstractRequestMatcherDsl() { when (rule) { is MatcherAuthorizationRule -> channelSecurity.requestMatchers(rule.matcher).requires(rule.rule) is PatternAuthorizationRule -> { - when (rule.patternType) { - PatternType.ANT -> channelSecurity.requestMatchers(rule.pattern).requires(rule.rule) - PatternType.MVC -> { - val introspector = channelSecurity.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java) - val mvcMatcher = MvcRequestMatcher.Builder(introspector) - .servletPath(rule.servletPath) - .pattern(rule.pattern) - mvcMatcher.setMethod(rule.httpMethod) - channelSecurity.requestMatchers(mvcMatcher).requires(rule.rule) - } + var builder = channelSecurity.applicationContext.getBeanProvider( + PathPatternRequestMatcher.Builder::class.java) + .getIfUnique(PathPatternRequestMatcher::withDefaults); + if (rule.servletPath != null) { + builder = builder.basePath(rule.servletPath) } + channelSecurity.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).requires(rule.rule) } } } diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-7.0.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-7.0.rnc index 323b785386..3e15354261 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-7.0.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-7.0.rnc @@ -1183,7 +1183,7 @@ hsts-options.attlist &= attribute preload {xsd:boolean}? cors = -## Element for configuration of CorsFilter. If no CorsFilter or CorsConfigurationSource is specified a HandlerMappingIntrospector is used as the CorsConfigurationSource +## Element for configuration of CorsFilter. A CorsConfigurationSource must be specified. If Spring MVC is present, then it will attempt to look up its `CorsConfigurationSource`. element cors { cors-options.attlist } cors-options.attlist &= ref? diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-7.0.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-7.0.xsd index 676b55a13d..59317aa2b4 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-7.0.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-7.0.xsd @@ -3317,8 +3317,8 @@ - Element for configuration of CorsFilter. If no CorsFilter or CorsConfigurationSource is - specified a HandlerMappingIntrospector is used as the CorsConfigurationSource + Element for configuration of CorsFilter. A CorsConfigurationSource must be specified. If + Spring MVC is present, then it will attempt to look up its `CorsConfigurationSource`. diff --git a/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java b/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java index 4794bce61a..71d879e399 100644 --- a/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java @@ -39,6 +39,7 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.util.pattern.PathPattern; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -121,7 +122,7 @@ public class FilterChainProxyConfigTests { private String getPattern(SecurityFilterChain chain) { RequestMatcher requestMatcher = ((DefaultSecurityFilterChain) chain).getRequestMatcher(); - return (String) ReflectionTestUtils.getField(requestMatcher, "pattern"); + return ((PathPattern) ReflectionTestUtils.getField(requestMatcher, "pattern")).getPatternString(); } private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) { diff --git a/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java b/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java index 4b338c116d..c44785faf3 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java +++ b/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java @@ -32,9 +32,10 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.util.Assert; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; + /** * @author Rob Winch * @@ -52,7 +53,7 @@ public class SecurityConfig { // @formatter:off http .authorizeRequests((requests) -> requests - .requestMatchers(new AntPathRequestMatcher("/*")).permitAll()) + .requestMatchers(pathPattern("/*")).permitAll()) .authenticationProvider(authenticationProvider()); // @formatter:on return http.build(); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java index 0a0b970968..6a5c6b0020 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java @@ -25,13 +25,12 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; /** * Tests for {@link AbstractRequestMatcherRegistry}. @@ -88,7 +87,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { http .authorizeRequests((requests) -> requests .anyRequest().authenticated() - .requestMatchers(new AntPathRequestMatcher("/demo/**")).permitAll()); + .requestMatchers(pathPattern("/demo/**")).permitAll()); return http.build(); // @formatter:on } @@ -100,12 +99,12 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { static class MvcMatchersAfterAnyRequestConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .authorizeRequests((requests) -> requests .anyRequest().authenticated() - .requestMatchers(new MvcRequestMatcher(introspector, "/demo/**")).permitAll()); + .requestMatchers(builder.matcher("/demo/**")).permitAll()); return http.build(); // @formatter:on } @@ -156,7 +155,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { http .authorizeRequests((requests) -> requests .anyRequest().authenticated() - .requestMatchers(new AntPathRequestMatcher("/**")).permitAll()); + .requestMatchers(pathPattern("/**")).permitAll()); return http.build(); // @formatter:on } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryNoMvcTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryNoMvcTests.java index 4d7c9a18ff..50d8aecb17 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryNoMvcTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryNoMvcTests.java @@ -21,9 +21,10 @@ import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.http.HttpMethod; import org.springframework.security.test.support.ClassPathExclusions; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import static org.assertj.core.api.Assertions.assertThat; @@ -41,22 +42,26 @@ public class AbstractRequestMatcherRegistryNoMvcTests { @BeforeEach public void setUp() { this.matcherRegistry = new TestRequestMatcherRegistry(); + GenericApplicationContext context = new GenericApplicationContext(); + context.registerBean(PathPatternRequestMatcher.Builder.class, PathPatternRequestMatcher::withDefaults); + context.refresh(); + this.matcherRegistry.setApplicationContext(context); } @Test - public void requestMatchersWhenPatternAndMvcNotPresentThenReturnAntPathRequestMatcherType() { + public void requestMatchersWhenPatternAndMvcNotPresentThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.requestMatchers("/path"); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } @Test - public void requestMatchersWhenHttpMethodAndPatternAndMvcNotPresentThenReturnAntPathRequestMatcherType() { + public void requestMatchersWhenHttpMethodAndPatternAndMvcNotPresentThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path"); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } @Test @@ -64,7 +69,7 @@ public class AbstractRequestMatcherRegistryNoMvcTests { List requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } private static class TestRequestMatcherRegistry extends AbstractRequestMatcherRegistry> { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java index 70f383c203..25476df821 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java @@ -16,47 +16,29 @@ package org.springframework.security.config.annotation.web; -import java.util.ArrayList; import java.util.List; import jakarta.servlet.DispatcherType; -import jakarta.servlet.Servlet; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.core.ResolvableType; import org.springframework.http.HttpMethod; -import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.config.ObjectPostProcessor; -import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry.DispatcherServletDelegatingRequestMatcher; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.test.SpringTestContext; -import org.springframework.security.web.servlet.MockServletContext; -import org.springframework.security.web.servlet.TestMockHttpServletMappings; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher; import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; /** * Tests for {@link AbstractRequestMatcherRegistry}. @@ -86,9 +68,9 @@ public class AbstractRequestMatcherRegistryTests { ObjectProvider> given = this.context.getBeanProvider(type); given(given).willReturn(postProcessors); given(postProcessors.getObject()).willReturn(NO_OP_OBJECT_POST_PROCESSOR); - given(this.context.getServletContext()).willReturn(MockServletContext.mvc()); + given(this.context.getBean(PathPatternRequestMatcher.Builder.class)) + .willReturn(PathPatternRequestMatcher.withDefaults()); this.matcherRegistry.setApplicationContext(this.context); - mockMvcIntrospector(true); } @Test @@ -110,24 +92,24 @@ public class AbstractRequestMatcherRegistryTests { } @Test - public void antMatchersWhenHttpMethodAndPatternParamsThenReturnAntPathRequestMatcherType() { + public void pathPatternWhenHttpMethodAndPatternParamsThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry - .requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name())); + .requestMatchers(pathPattern(HttpMethod.GET, "/a.*")); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } @Test - public void antMatchersWhenPatternParamThenReturnAntPathRequestMatcherType() { - List requestMatchers = this.matcherRegistry.requestMatchers(new AntPathRequestMatcher("/a.*")); + public void pathPatternWhenPatternParamThenReturnPathPatternRequestMatcherType() { + List requestMatchers = this.matcherRegistry.requestMatchers(pathPattern("/a.*")); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } @Test - public void dispatcherTypeMatchersWhenHttpMethodAndPatternParamsThenReturnAntPathRequestMatcherType() { + public void dispatcherTypeMatchersWhenHttpMethodAndPatternParamsThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(HttpMethod.GET, DispatcherType.ASYNC); assertThat(requestMatchers).isNotEmpty(); @@ -136,7 +118,7 @@ public class AbstractRequestMatcherRegistryTests { } @Test - public void dispatcherMatchersWhenPatternParamThenReturnAntPathRequestMatcherType() { + public void dispatcherMatchersWhenPatternParamThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(DispatcherType.INCLUDE); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); @@ -144,252 +126,36 @@ public class AbstractRequestMatcherRegistryTests { } @Test - public void requestMatchersWhenPatternAndMvcPresentThenReturnMvcRequestMatcherType() { + public void requestMatchersWhenPatternAndMvcPresentThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.requestMatchers("/path"); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } @Test - public void requestMatchersWhenHttpMethodAndPatternAndMvcPresentThenReturnMvcRequestMatcherType() { + public void requestMatchersWhenHttpMethodAndPatternAndMvcPresentThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path"); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } @Test - public void requestMatchersWhenHttpMethodAndMvcPresentThenReturnMvcRequestMatcherType() { + public void requestMatchersWhenHttpMethodAndMvcPresentThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class); - } - - @Test - public void requestMatchersWhenMvcPresentInClassPathAndMvcIntrospectorBeanNotAvailableThenException() { - mockMvcIntrospector(false); - assertThatExceptionOfType(NoSuchBeanDefinitionException.class) - .isThrownBy(() -> this.matcherRegistry.requestMatchers("/path")) - .withMessageContaining( - "Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext"); - } - - @Test - public void requestMatchersWhenNoDispatcherServletThenAntPathRequestMatcherType() { - mockMvcIntrospector(true); - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - MockHttpServletRequest request = new MockHttpServletRequest(); - List requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).isNotEmpty(); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class)) - .extracting((matcher) -> matcher.requestMatcher(request)) - .isInstanceOf(AntPathRequestMatcher.class); - servletContext.addServlet("servletOne", Servlet.class).addMapping("/one"); - servletContext.addServlet("servletTwo", Servlet.class).addMapping("/two"); - requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).isNotEmpty(); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class)) - .extracting((matcher) -> matcher.requestMatcher(request)) - .isInstanceOf(AntPathRequestMatcher.class); - servletContext.addServlet("servletOne", Servlet.class); - servletContext.addServlet("servletTwo", Servlet.class); - requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).isNotEmpty(); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class)) - .extracting((matcher) -> matcher.requestMatcher(request)) - .isInstanceOf(AntPathRequestMatcher.class); - } - - // gh-14418 - @Test - public void requestMatchersWhenNoDispatcherServletMockMvcThenMvcRequestMatcherType() throws Exception { - MockServletContext servletContext = new MockServletContext(); - try (SpringTestContext spring = new SpringTestContext(this)) { - spring.register(MockMvcConfiguration.class) - .postProcessor((context) -> context.setServletContext(servletContext)) - .autowire(); - this.matcherRegistry.setApplicationContext(spring.getContext()); - MockMvc mvc = MockMvcBuilders.webAppContextSetup(spring.getContext()).build(); - MockHttpServletRequest request = mvc.perform(get("/")).andReturn().getRequest(); - List requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).isNotEmpty(); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class)) - .extracting((matcher) -> matcher.requestMatcher(request)) - .isInstanceOf(MvcRequestMatcher.class); - servletContext.addServlet("servletOne", Servlet.class).addMapping("/one"); - servletContext.addServlet("servletTwo", Servlet.class).addMapping("/two"); - requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).isNotEmpty(); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class)) - .extracting((matcher) -> matcher.requestMatcher(request)) - .isInstanceOf(MvcRequestMatcher.class); - servletContext.addServlet("servletOne", Servlet.class); - servletContext.addServlet("servletTwo", Servlet.class); - requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).isNotEmpty(); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class)) - .extracting((matcher) -> matcher.requestMatcher(request)) - .isInstanceOf(MvcRequestMatcher.class); - } - } - - @Test - public void requestMatchersWhenAmbiguousServletsThenException() { - mockMvcIntrospector(true); - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/"); - servletContext.addServlet("servletTwo", DispatcherServlet.class).addMapping("/servlet/*"); - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> this.matcherRegistry.requestMatchers("/**")); - } - - @Test - public void requestMatchersWhenMultipleDispatcherServletMappingsThenException() { - mockMvcIntrospector(true); - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/", "/mvc/*"); - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> this.matcherRegistry.requestMatchers("/**")); - } - - @Test - public void requestMatchersWhenPathDispatcherServletAndOtherServletsThenException() { - mockMvcIntrospector(true); - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/mvc/*"); - servletContext.addServlet("default", Servlet.class).addMapping("/"); - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> this.matcherRegistry.requestMatchers("/**")); - } - - @Test - public void requestMatchersWhenUnmappableServletsThenSkips() { - mockMvcIntrospector(true); - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/"); - servletContext.addServlet("servletTwo", Servlet.class); - List requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isInstanceOf(MvcRequestMatcher.class); - } - - @Test - public void requestMatchersWhenOnlyDispatcherServletThenAllows() { - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/mvc/*"); - List requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isInstanceOf(MvcRequestMatcher.class); - } - - @Test - public void requestMatchersWhenImplicitServletsThenAllows() { - mockMvcIntrospector(true); - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - servletContext.addServlet("defaultServlet", Servlet.class); - servletContext.addServlet("jspServlet", Servlet.class).addMapping("*.jsp", "*.jspx"); - servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/"); - List requestMatchers = this.matcherRegistry.requestMatchers("/**"); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isInstanceOf(DispatcherServletDelegatingRequestMatcher.class); - } - - @Test - public void requestMatchersWhenPathBasedNonDispatcherServletThenAllows() { - MockServletContext servletContext = new MockServletContext(); - given(this.context.getServletContext()).willReturn(servletContext); - servletContext.addServlet("path", Servlet.class).addMapping("/services/*"); - servletContext.addServlet("default", DispatcherServlet.class).addMapping("/"); - List requestMatchers = this.matcherRegistry.requestMatchers("/services/*"); - assertThat(requestMatchers).hasSize(1); - assertThat(requestMatchers.get(0)).isInstanceOf(DispatcherServletDelegatingRequestMatcher.class); - MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/services/endpoint"); - request.setHttpServletMapping(TestMockHttpServletMappings.defaultMapping()); - assertThat(requestMatchers.get(0).matcher(request).isMatch()).isTrue(); - request.setHttpServletMapping(TestMockHttpServletMappings.path(request, "/services")); - request.setServletPath("/services"); - request.setPathInfo("/endpoint"); - assertThat(requestMatchers.get(0).matcher(request).isMatch()).isTrue(); - } - - @Test - public void matchesWhenDispatcherServletThenMvc() { - MockServletContext servletContext = new MockServletContext(); - servletContext.addServlet("default", DispatcherServlet.class).addMapping("/"); - servletContext.addServlet("path", Servlet.class).addMapping("/services/*"); - MvcRequestMatcher mvc = mock(MvcRequestMatcher.class); - AntPathRequestMatcher ant = mock(AntPathRequestMatcher.class); - RequestMatcher requestMatcher = new DispatcherServletDelegatingRequestMatcher(ant, mvc); - MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/services/endpoint"); - request.setHttpServletMapping(TestMockHttpServletMappings.defaultMapping()); - assertThat(requestMatcher.matches(request)).isFalse(); - verify(mvc).matches(request); - verifyNoInteractions(ant); - request.setHttpServletMapping(TestMockHttpServletMappings.path(request, "/services")); - assertThat(requestMatcher.matches(request)).isFalse(); - verify(ant).matches(request); - verifyNoMoreInteractions(mvc); - } - - @Test - public void matchesWhenNoMappingThenException() { - MockServletContext servletContext = new MockServletContext(); - servletContext.addServlet("default", DispatcherServlet.class).addMapping("/"); - servletContext.addServlet("path", Servlet.class).addMapping("/services/*"); - MvcRequestMatcher mvc = mock(MvcRequestMatcher.class); - AntPathRequestMatcher ant = mock(AntPathRequestMatcher.class); - RequestMatcher requestMatcher = new DispatcherServletDelegatingRequestMatcher(ant, mvc); - MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/services/endpoint"); - assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> requestMatcher.matcher(request)); - } - - private void mockMvcIntrospector(boolean isPresent) { - ApplicationContext context = this.matcherRegistry.getApplicationContext(); - given(context.containsBean("mvcHandlerMappingIntrospector")).willReturn(isPresent); + assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class); } private static class TestRequestMatcherRegistry extends AbstractRequestMatcherRegistry> { - @Override - public List requestMatchers(RequestMatcher... requestMatchers) { - return unwrap(super.requestMatchers(requestMatchers)); - } - @Override protected List chainRequestMatchers(List requestMatchers) { return requestMatchers; } - private List unwrap(List wrappedMatchers) { - List requestMatchers = new ArrayList<>(); - for (RequestMatcher requestMatcher : wrappedMatchers) { - if (requestMatcher instanceof DeferredRequestMatcher) { - DeferredRequestMatcher deferred = (DeferredRequestMatcher) requestMatcher; - WebApplicationContext web = (WebApplicationContext) getApplicationContext(); - requestMatchers.add(deferred.requestMatcher(web.getServletContext())); - } - else { - requestMatchers.add(requestMatcher); - } - } - return requestMatchers; - } - } @Configuration diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java index 7a4cb72b10..b6c53a05b4 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java @@ -39,7 +39,6 @@ import org.springframework.security.core.userdetails.PasswordEncodedUser; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -49,6 +48,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.springframework.security.config.Customizer.withDefaults; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -150,8 +150,8 @@ public class HttpConfigurationTests { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(new AntPathRequestMatcher("/api/**")) - .requestMatchers(new AntPathRequestMatcher("/oauth/**"))) + .requestMatchers(pathPattern("/api/**")) + .requestMatchers(pathPattern("/oauth/**"))) .authorizeRequests((requests) -> requests .anyRequest().hasRole("USER")) .httpBasic(withDefaults()); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java index 6aa7666b5d..54fb1f390d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java @@ -54,8 +54,8 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.context.NullSecurityContextRepository; import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.stereotype.Controller; @@ -75,6 +75,7 @@ import static org.springframework.security.config.Customizer.withDefaults; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; @@ -195,13 +196,13 @@ public class NamespaceHttpTests { } @Test // http@request-matcher-ref ant - public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() { + public void configureWhenAntPatternMatchingThenPathPatternRequestMatcherUsed() { this.spring.register(RequestMatcherAntConfig.class).autowire(); FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class); DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains() .get(0); - assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class); + assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class); } @Test // http@request-matcher-ref regex @@ -226,21 +227,19 @@ public class NamespaceHttpTests { } @Test // http@security=none - public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() { + public void configureWhenIgnoredAntPatternsThenPathPatternRequestMatcherUsedWithNoFilters() { this.spring.register(SecurityNoneConfig.class).autowire(); FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class); DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains() .get(0); - assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class); - assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()) - .isEqualTo("/resources/**"); + assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class); + assertThat(securityFilterChain.getRequestMatcher()).isEqualTo(pathPattern("/resources/**")); assertThat(securityFilterChain.getFilters()).isEmpty(); assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class); securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1); - assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class); - assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()) - .isEqualTo("/public/**"); + assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class); + assertThat(securityFilterChain.getRequestMatcher()).isEqualTo(pathPattern("/public/**")); assertThat(securityFilterChain.getFilters()).isEmpty(); } @@ -482,7 +481,7 @@ public class NamespaceHttpTests { SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatcher(new AntPathRequestMatcher("/api/**")); + .securityMatcher(pathPattern("/api/**")); return http.build(); // @formatter:on } @@ -534,8 +533,9 @@ public class NamespaceHttpTests { @Bean WebSecurityCustomizer webSecurityCustomizer() { + PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults(); return (web) -> web.ignoring() - .requestMatchers(new AntPathRequestMatcher("/resources/**"), new AntPathRequestMatcher("/public/**")); + .requestMatchers(builder.matcher("/resources/**"), builder.matcher("/public/**")); } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidatorTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidatorTests.java index 450a3dfdc1..62845140c6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidatorTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidatorTests.java @@ -31,7 +31,7 @@ import org.springframework.security.web.UnreachableFilterChainException; import org.springframework.security.web.access.ExceptionTranslationFilter; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatchers; @@ -49,6 +49,8 @@ public class WebSecurityFilterChainValidatorTests { private final WebSecurityFilterChainValidator validator = new WebSecurityFilterChainValidator(); + private final PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults(); + @Mock private AnonymousAuthenticationFilter authenticationFilter; @@ -60,7 +62,7 @@ public class WebSecurityFilterChainValidatorTests { @Test void validateWhenFilterSecurityInterceptorConfiguredThenValidates() { - SecurityFilterChain chain = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"), + SecurityFilterChain chain = new DefaultSecurityFilterChain(this.builder.matcher("/api"), this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor); FilterChainProxy proxy = new FilterChainProxy(List.of(chain)); @@ -69,7 +71,7 @@ public class WebSecurityFilterChainValidatorTests { @Test void validateWhenAnyRequestMatcherIsPresentThenUnreachableFilterChainException() { - SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"), + SecurityFilterChain chain1 = new DefaultSecurityFilterChain(this.builder.matcher("/api"), this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor); SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE, this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor); @@ -84,9 +86,9 @@ public class WebSecurityFilterChainValidatorTests { @Test void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() { - SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"), + SecurityFilterChain chain1 = new DefaultSecurityFilterChain(this.builder.matcher("/api"), this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor); - SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"), + SecurityFilterChain chain2 = new DefaultSecurityFilterChain(this.builder.matcher("/api"), this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor); List chains = new ArrayList<>(); chains.add(chain2); @@ -99,10 +101,12 @@ public class WebSecurityFilterChainValidatorTests { @Test void validateWhenSameComposedRequestMatchersArePresentThenUnreachableFilterChainException() { - RequestMatcher matcher1 = RequestMatchers.anyOf(RequestMatchers.allOf(AntPathRequestMatcher.antMatcher("/api"), - AntPathRequestMatcher.antMatcher("*.do")), AntPathRequestMatcher.antMatcher("/admin")); - RequestMatcher matcher2 = RequestMatchers.anyOf(RequestMatchers.allOf(AntPathRequestMatcher.antMatcher("/api"), - AntPathRequestMatcher.antMatcher("*.do")), AntPathRequestMatcher.antMatcher("/admin")); + RequestMatcher matcher1 = RequestMatchers.anyOf( + RequestMatchers.allOf(this.builder.matcher("/api"), this.builder.matcher("/*.do")), + this.builder.matcher("/admin")); + RequestMatcher matcher2 = RequestMatchers.anyOf( + RequestMatchers.allOf(this.builder.matcher("/api"), this.builder.matcher("/*.do")), + this.builder.matcher("/admin")); SecurityFilterChain chain1 = new DefaultSecurityFilterChain(matcher1, this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor); SecurityFilterChain chain2 = new DefaultSecurityFilterChain(matcher2, this.authenticationFilter, diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java index 2b58af889f..6f10a692fc 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java @@ -42,12 +42,11 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.config.Customizer.withDefaults; @@ -130,8 +129,8 @@ public class WebSecurityTests { static class MvcMatcherConfig { @Bean - WebSecurityCustomizer webSecurityCustomizer(HandlerMappingIntrospector introspector) { - return (web) -> web.ignoring().requestMatchers(new MvcRequestMatcher(introspector, "/path")); + WebSecurityCustomizer webSecurityCustomizer(PathPatternRequestMatcher.Builder builder) { + return (web) -> web.ignoring().requestMatchers(builder.matcher("/path")); } @Bean @@ -168,9 +167,10 @@ public class WebSecurityTests { static class MvcMatcherServletPathConfig { @Bean - WebSecurityCustomizer webSecurityCustomizer(HandlerMappingIntrospector introspector) { - MvcRequestMatcher.Builder builder = new MvcRequestMatcher.Builder(introspector).servletPath("/spring"); - return (web) -> web.ignoring().requestMatchers(builder.pattern("/path")).requestMatchers("/notused"); + WebSecurityCustomizer webSecurityCustomizer(PathPatternRequestMatcher.Builder builder) { + return (web) -> web.ignoring() + .requestMatchers(builder.basePath("/spring").matcher("/path")) + .requestMatchers("/notused"); } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests.java index 90297c75ef..866cd95503 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests.java @@ -26,20 +26,19 @@ import org.springframework.security.authentication.TestAuthentication; import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners; import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer; -import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; /** - * Checks that HandlerMappingIntrospectorRequestTransformer is autowired into + * Checks that + * {@link org.springframework.security.web.access.PathPatternRequestTransformer} is + * autowired into * {@link org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator}. * * @author Rob Winch @@ -59,20 +58,8 @@ public class AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests { WebInvocationPrivilegeEvaluator wipe; @Test - void mvcEnabledConfigThenHandlerMappingIntrospectorRequestTransformerBeanExists() { - this.spring.register(MvcEnabledConfig.class).autowire(); - assertThat(this.requestTransformer).isInstanceOf(HandlerMappingIntrospectorRequestTransformer.class); - } - - @Test - void mvcNotEnabledThenNoRequestTransformerBeanExists() { - this.spring.register(MvcNotEnabledConfig.class).autowire(); - assertThat(this.requestTransformer).isNull(); - } - - @Test - void mvcNotEnabledAndTransformerThenWIPEDelegatesToTransformer() { - this.spring.register(MvcNotEnabledConfig.class, TransformerConfig.class).autowire(); + void webAndTransformerThenWIPEDelegatesToTransformer() { + this.spring.register(WebConfig.class, TransformerConfig.class).autowire(); this.wipe.isAllowed("/uri", TestAuthentication.authenticatedUser()); @@ -90,15 +77,8 @@ public class AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests { } @Configuration - @EnableWebMvc @EnableWebSecurity - static class MvcEnabledConfig { - - } - - @Configuration - @EnableWebSecurity - static class MvcNotEnabledConfig { + static class WebConfig { } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HandlerMappingIntrospectorCacheFilterConfigTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HandlerMappingIntrospectorCacheFilterConfigTests.java deleted file mode 100644 index 865b99ee21..0000000000 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HandlerMappingIntrospectorCacheFilterConfigTests.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2002-2023 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 java.io.IOException; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.test.SpringTestContext; -import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.stereotype.Component; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector.CachedResult; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; - -/** - * @author Rob Winch - */ -@ContextConfiguration -@WebAppConfiguration -@ExtendWith({ SpringExtension.class }) -@SecurityTestExecutionListeners -class HandlerMappingIntrospectorCacheFilterConfigTests { - - @Autowired - WebApplicationContext context; - - MockMvc mockMvc; - - public final SpringTestContext spring = new SpringTestContext(this); - - @Autowired(required = false) - MvcEnabledConfig.CaptureHandlerMappingIntrospectorCache captureCacheFilter; - - @Autowired(required = false) - HandlerMappingIntrospector hmi; - - @Test - @WithMockUser - void hmiIsCached() throws Exception { - this.spring.register(MvcEnabledConfig.class).autowire(); - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(springSecurity()) - .addFilter(this.captureCacheFilter) - .build(); - this.mockMvc.perform(get("/")); - assertThat(this.captureCacheFilter.cachedResult).isNotNull(); - } - - @Test - @WithMockUser - void configurationLoadsIfNoHMI() { - // no BeanCreationException due to missing HandlerMappingIntrospector - this.spring.register(MvcNotEnabledConfig.class).autowire(); - // ensure assumption of HandlerMappingIntrospector is null is true - assertThat(this.hmi).isNull(); - } - - @Configuration - @EnableWebMvc - @EnableWebSecurity - static class MvcEnabledConfig { - - @Component - static class CaptureHandlerMappingIntrospectorCache implements Filter { - - final HandlerMappingIntrospector hmi; - - private CachedResult cachedResult; - - CaptureHandlerMappingIntrospectorCache(HandlerMappingIntrospector hmi) { - this.hmi = hmi; - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - // capture the old cached value to check that caching has already occurred - this.cachedResult = this.hmi.setCache((HttpServletRequest) request); - chain.doFilter(request, response); - } - - } - - } - - @Configuration - @EnableWebSecurity - static class MvcNotEnabledConfig { - - } - -} diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java index 311bae361d..769c8d6277 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java @@ -62,8 +62,6 @@ import org.springframework.security.web.access.PathPatternRequestTransformer; import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; -import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.util.ClassUtils; import org.springframework.web.bind.annotation.GetMapping; @@ -78,6 +76,7 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -106,14 +105,13 @@ public class WebSecurityConfigurationTests { FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); List filterChains = filterChainProxy.getFilterChains(); assertThat(filterChains).hasSize(4); - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setServletPath("/role1/**"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/role1/**"); assertThat(filterChains.get(0).matches(request)).isTrue(); - request.setServletPath("/role2/**"); + request = new MockHttpServletRequest("GET", "/role2/**"); assertThat(filterChains.get(1).matches(request)).isTrue(); - request.setServletPath("/role3/**"); + request = new MockHttpServletRequest("GET", "/role3/**"); assertThat(filterChains.get(2).matches(request)).isTrue(); - request.setServletPath("/**"); + request = new MockHttpServletRequest("GET", "/**"); assertThat(filterChains.get(3).matches(request)).isTrue(); } @@ -123,10 +121,9 @@ public class WebSecurityConfigurationTests { FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); List filterChains = filterChainProxy.getFilterChains(); assertThat(filterChains).hasSize(2); - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setServletPath("/role1/**"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/role1/**"); assertThat(filterChains.get(0).matches(request)).isTrue(); - request.setServletPath("/role2/**"); + request = new MockHttpServletRequest("GET", "/role2/**"); assertThat(filterChains.get(1).matches(request)).isTrue(); } @@ -240,14 +237,13 @@ public class WebSecurityConfigurationTests { FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); List filterChains = filterChainProxy.getFilterChains(); assertThat(filterChains).hasSize(3); - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setServletPath("/ignore1"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1"); assertThat(filterChains.get(0).matches(request)).isTrue(); assertThat(filterChains.get(0).getFilters()).isEmpty(); - request.setServletPath("/ignore2"); + request = new MockHttpServletRequest("GET", "/ignore2"); assertThat(filterChains.get(1).matches(request)).isTrue(); assertThat(filterChains.get(1).getFilters()).isEmpty(); - request.setServletPath("/test/**"); + request = new MockHttpServletRequest("GET", "/test/**"); assertThat(filterChains.get(2).matches(request)).isTrue(); } @@ -257,16 +253,15 @@ public class WebSecurityConfigurationTests { FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); List filterChains = filterChainProxy.getFilterChains(); assertThat(filterChains).hasSize(3); - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setServletPath("/ignore1"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1"); assertThat(filterChains.get(0).matches(request)).isTrue(); assertThat(filterChains.get(0).getFilters()).isEmpty(); - request.setServletPath("/ignore2"); + request = new MockHttpServletRequest("GET", "/ignore2"); assertThat(filterChains.get(1).matches(request)).isTrue(); assertThat(filterChains.get(1).getFilters()).isEmpty(); - request.setServletPath("/role1/**"); + request = new MockHttpServletRequest("GET", "/role1/**"); assertThat(filterChains.get(2).matches(request)).isTrue(); - request.setServletPath("/test/**"); + request = new MockHttpServletRequest("GET", "/test/**"); assertThat(filterChains.get(2).matches(request)).isFalse(); } @@ -276,11 +271,10 @@ public class WebSecurityConfigurationTests { FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); List filterChains = filterChainProxy.getFilterChains(); assertThat(filterChains).hasSize(3); - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setServletPath("/ignore1"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1"); assertThat(filterChains.get(0).matches(request)).isTrue(); assertThat(filterChains.get(0).getFilters()).isEmpty(); - request.setServletPath("/ignore2"); + request = new MockHttpServletRequest("GET", "/ignore2"); assertThat(filterChains.get(1).matches(request)).isTrue(); assertThat(filterChains.get(1).getFilters()).isEmpty(); } @@ -420,7 +414,7 @@ public class WebSecurityConfigurationTests { SecurityFilterChain filterChain1(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role1/**")) + .securityMatcher(pathPattern("/role1/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("1") ) @@ -433,7 +427,7 @@ public class WebSecurityConfigurationTests { SecurityFilterChain filterChain2(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role2/**")) + .securityMatcher(pathPattern("/role2/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("2") ) @@ -446,7 +440,7 @@ public class WebSecurityConfigurationTests { SecurityFilterChain filterChain3(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role3/**")) + .securityMatcher(pathPattern("/role3/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("3") ) @@ -477,7 +471,7 @@ public class WebSecurityConfigurationTests { SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role1/**")) + .securityMatcher(pathPattern("/role1/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("1") ) @@ -734,7 +728,7 @@ public class WebSecurityConfigurationTests { SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role1/**")) + .securityMatcher(pathPattern("/role1/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("1") ) @@ -773,7 +767,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain path1(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/path1/**"))) .authorizeRequests((requests) -> requests.anyRequest().authenticated()); // @formatter:on return http.build(); @@ -797,7 +791,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain path1(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/path1/**"))) .authorizeRequests((requests) -> requests.anyRequest().authenticated()); // @formatter:on return http.build(); @@ -822,7 +816,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/user"))) .authorizeRequests((requests) -> requests.anyRequest().hasRole("USER")); // @formatter:on return http.build(); @@ -833,7 +827,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain path1(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/admin"))) .authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN")); // @formatter:on return http.build(); @@ -864,7 +858,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/user"))) .authorizeRequests((requests) -> requests.anyRequest().hasRole("USER")); // @formatter:on return http.build(); @@ -875,7 +869,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain admin(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/admin"))) .authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN")); // @formatter:on return http.build(); @@ -911,7 +905,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/user"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/user"))) .authorizeHttpRequests((authorize) -> authorize.anyRequest().hasRole("USER")); // @formatter:on return http.build(); @@ -922,7 +916,7 @@ public class WebSecurityConfigurationTests { public SecurityFilterChain admin(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/admin"))) + .securityMatchers((requests) -> requests.requestMatchers(pathPattern("/admin"))) .authorizeHttpRequests((authorize) -> authorize.anyRequest().hasRole("ADMIN")); // @formatter:on return http.build(); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java index e34de7c883..9de9b627c7 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java @@ -22,11 +22,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; public class AbstractConfigAttributeRequestMatcherRegistryTests { @@ -55,19 +56,18 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests { } @Test - public void testGetRequestMatcherIsTypeAntPathRequestMatcher() { - List requestMatchers = this.registry - .requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name())); + public void testGetRequestMatcherIsTypePathPatternRequestMatcher() { + List requestMatchers = this.registry.requestMatchers(pathPattern(HttpMethod.GET, "/a.*")); for (RequestMatcher requestMatcher : requestMatchers) { - assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class); + assertThat(requestMatcher).isInstanceOf(PathPatternRequestMatcher.class); } } @Test - public void testRequestMatcherIsTypeAntPathRequestMatcher() { - List requestMatchers = this.registry.requestMatchers(new AntPathRequestMatcher("/a.*")); + public void testRequestMatcherIsTypePathPatternRequestMatcher() { + List requestMatchers = this.registry.requestMatchers(pathPattern("/a.*")); for (RequestMatcher requestMatcher : requestMatchers) { - assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class); + assertThat(requestMatcher).isInstanceOf(PathPatternRequestMatcher.class); } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java index b2bd973bee..7f807a8b23 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java @@ -55,7 +55,6 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults; import org.springframework.security.config.observation.SecurityObservationSettings; import org.springframework.security.config.test.SpringTestContext; 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.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -68,7 +67,6 @@ import org.springframework.security.web.access.expression.WebExpressionAuthoriza import org.springframework.security.web.access.intercept.AuthorizationFilter; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.stereotype.Component; import org.springframework.test.web.servlet.MockMvc; @@ -81,7 +79,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -148,7 +145,7 @@ public class AuthorizeHttpRequestsConfigurerTests { public void configureWhenMvcMatcherAfterAnyRequestThenException() { assertThatExceptionOfType(BeanCreationException.class) .isThrownBy(() -> this.spring.register(AfterAnyRequestConfig.class).autowire()) - .withMessageContaining("Can't configure mvcMatchers after anyRequest"); + .withMessageContaining("Can't configure requestMatchers after anyRequest"); } @Test @@ -689,7 +686,7 @@ public class AuthorizeHttpRequestsConfigurerTests { @Test public void requestMatchersWhenMultipleDispatcherServletsAndPathBeanThenAllows() throws Exception { - this.spring.register(MvcRequestMatcherBuilderConfig.class, BasicController.class) + this.spring.register(PathPatternRequestMatcherBuilderConfig.class, BasicController.class) .postProcessor((context) -> context.getServletContext() .addServlet("otherDispatcherServlet", DispatcherServlet.class) .addMapping("/mvc")) @@ -1063,13 +1060,11 @@ public class AuthorizeHttpRequestsConfigurerTests { static class ServletPathConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off return http .authorizeHttpRequests((authorize) -> authorize - .requestMatchers(mvcMatcherBuilder.pattern("/")).hasRole("ADMIN") + .requestMatchers(builder.basePath("/spring").matcher("/")).hasRole("ADMIN") ) .build(); // @formatter:on @@ -1358,7 +1353,7 @@ public class AuthorizeHttpRequestsConfigurerTests { @Configuration @EnableWebSecurity @EnableWebMvc - static class MvcRequestMatcherBuilderConfig { + static class PathPatternRequestMatcherBuilderConfig { @Bean SecurityFilterChain security(HttpSecurity http) throws Exception { @@ -1394,11 +1389,6 @@ public class AuthorizeHttpRequestsConfigurerTests { return http.build(); } - @Bean - PathPatternRequestMatcherBuilderFactoryBean pathPatternFactoryBean() { - return new PathPatternRequestMatcherBuilderFactoryBean(); - } - } @Configuration diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java index 4ecbd91d48..58851b5c57 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java @@ -42,17 +42,17 @@ import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.security.web.servlet.MockServletContext; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; +import org.springframework.web.util.pattern.PathPatternParser; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.spy; import static org.springframework.security.config.Customizer.withDefaults; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; /** * @author Rob Winch @@ -126,11 +126,13 @@ public class AuthorizeRequestsTests { loadConfig(AntPatchersPathVariables.class); this.request.setRequestURI("/USER/user"); this.request.setServletPath("/USER/user"); + this.request.setRequestURI("/USER/user"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); this.setup(); this.request.setRequestURI("/USER/deny"); this.request.setServletPath("/USER/deny"); + this.request.setRequestURI("/USER/deny"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN); } @@ -204,7 +206,7 @@ public class AuthorizeRequestsTests { // @formatter:off http .authorizeRequests((requests) -> requests - .requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll()); + .requestMatchers(pathPattern(HttpMethod.POST, "/**")).denyAll()); // @formatter:on return http.build(); } @@ -225,7 +227,7 @@ public class AuthorizeRequestsTests { // @formatter:off http .authorizeRequests((authorize) -> authorize - .requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll() + .requestMatchers(pathPattern(HttpMethod.POST, "/**")).denyAll() ); // @formatter:on return http.build(); @@ -244,10 +246,13 @@ public class AuthorizeRequestsTests { @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + PathPatternParser parser = new PathPatternParser(); + parser.setCaseSensitive(false); + PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withPathPatternParser(parser); // @formatter:off http .authorizeRequests((requests) -> requests - .requestMatchers(new AntPathRequestMatcher("/user/{user}", null, false)).access("#user == 'user'") + .requestMatchers(builder.matcher("/user/{user}")).access("#user == 'user'") .anyRequest().denyAll()); // @formatter:on return http.build(); @@ -266,10 +271,13 @@ public class AuthorizeRequestsTests { @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + PathPatternParser parser = new PathPatternParser(); + parser.setCaseSensitive(false); + PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withPathPatternParser(parser); // @formatter:off http .authorizeRequests((requests) -> requests - .requestMatchers(new AntPathRequestMatcher("/user/{userName}", null, false)).access("#userName == 'user'") + .requestMatchers(builder.matcher("/user/{userName}")).access("#userName == 'user'") .anyRequest().denyAll()); // @formatter:on return http.build(); @@ -383,14 +391,13 @@ public class AuthorizeRequestsTests { static class MvcMatcherServletPathConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { + PathPatternRequestMatcher.Builder spring = builder.basePath("/spring"); // @formatter:off http .httpBasic(withDefaults()) .authorizeRequests((requests) -> requests - .requestMatchers(mvcMatcherBuilder.pattern("/path")).denyAll()); + .requestMatchers(spring.matcher("/path")).denyAll()); // @formatter:on return http.build(); } @@ -418,14 +425,13 @@ public class AuthorizeRequestsTests { static class MvcMatcherServletPathInLambdaConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { + PathPatternRequestMatcher.Builder spring = builder.basePath("/spring"); // @formatter:off http .httpBasic(withDefaults()) .authorizeRequests((authorize) -> authorize - .requestMatchers(mvcMatcherBuilder.pattern("/path")).denyAll() + .requestMatchers(spring.matcher("/path")).denyAll() ); // @formatter:on return http.build(); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java index 377445bb0a..2e8c1e1f0c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java @@ -28,13 +28,13 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.config.test.SpringTestContextExtension; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; @@ -109,7 +109,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { // @formatter:off http .csrf((csrf) -> csrf - .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path")) + .requireCsrfProtectionMatcher(pathPattern("/path")) .ignoringRequestMatchers(this.requestMatcher)); return http.build(); // @formatter:on @@ -129,7 +129,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { // @formatter:off http .csrf((csrf) -> csrf - .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path")) + .requireCsrfProtectionMatcher(pathPattern("/path")) .ignoringRequestMatchers(this.requestMatcher) ); return http.build(); @@ -149,7 +149,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { // @formatter:off http .csrf((csrf) -> csrf - .ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf")) + .ignoringRequestMatchers(pathPattern("/no-csrf")) .ignoringRequestMatchers(this.requestMatcher)); return http.build(); // @formatter:on @@ -169,7 +169,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { // @formatter:off http .csrf((csrf) -> csrf - .ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf")) + .ignoringRequestMatchers(pathPattern("/no-csrf")) .ignoringRequestMatchers(this.requestMatcher) ); return http.build(); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java index ce08191199..6942e70059 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java @@ -57,7 +57,6 @@ import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler import org.springframework.security.web.firewall.StrictHttpFirewall; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -84,6 +83,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head; @@ -906,7 +906,7 @@ public class CsrfConfigurerTests { http .formLogin(withDefaults()) .logout((logout) -> logout - .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))); + .logoutRequestMatcher(pathPattern("/logout"))); return http.build(); // @formatter:on } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java index 46d0fbe54a..93af0fe725 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java @@ -128,8 +128,7 @@ public class DefaultFiltersTests { public void defaultFiltersPermitAll() throws IOException, ServletException { this.spring.register(DefaultFiltersConfigPermitAll.class, UserDetailsServiceConfig.class); MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest("POST", ""); - request.setServletPath("/logout"); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout"); CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN"); CsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); repository.saveToken(csrfToken, request, response); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java index ad1de31fe2..d76e759edf 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java @@ -32,11 +32,11 @@ import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.access.AccessDeniedHandlerImpl; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -92,7 +92,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { .exceptionHandling((handling) -> handling .defaultAccessDeniedHandlerFor( this.teapotDeniedHandler, - new AntPathRequestMatcher("/hello/**")) + pathPattern("/hello/**")) .defaultAccessDeniedHandlerFor( new AccessDeniedHandlerImpl(), AnyRequestMatcher.INSTANCE)); @@ -119,7 +119,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { .exceptionHandling((exceptionHandling) -> exceptionHandling .defaultAccessDeniedHandlerFor( this.teapotDeniedHandler, - new AntPathRequestMatcher("/hello/**") + pathPattern("/hello/**") ) .defaultAccessDeniedHandlerFor( new AccessDeniedHandlerImpl(), @@ -148,7 +148,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { .exceptionHandling((handling) -> handling .defaultAccessDeniedHandlerFor( this.teapotDeniedHandler, - new AntPathRequestMatcher("/hello/**"))); + pathPattern("/hello/**"))); return http.build(); // @formatter:on } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java index ef85cab20e..212aa8fd41 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java @@ -36,12 +36,11 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.config.Customizer.withDefaults; @@ -160,14 +159,13 @@ public class HttpSecurityRequestMatchersTests { @Bean @Order(Ordered.HIGHEST_PRECEDENCE) - SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); + SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((requests) -> requests - .requestMatchers(mvcMatcherBuilder.pattern("/test-1")) - .requestMatchers(mvcMatcherBuilder.pattern("/test-2")) - .requestMatchers(mvcMatcherBuilder.pattern("/test-3")) + .requestMatchers(builder.matcher("/test-1")) + .requestMatchers(builder.matcher("/test-2")) + .requestMatchers(builder.matcher("/test-3")) ) .authorizeRequests((authorize) -> authorize.anyRequest().denyAll()) .httpBasic(withDefaults()); @@ -176,12 +174,11 @@ public class HttpSecurityRequestMatchersTests { } @Bean - SecurityFilterChain second(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); + SecurityFilterChain second(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((requests) -> requests - .requestMatchers(mvcMatcherBuilder.pattern("/test-1")) + .requestMatchers(builder.matcher("/test-1")) ) .authorizeRequests((authorize) -> authorize .anyRequest().permitAll() @@ -209,14 +206,13 @@ public class HttpSecurityRequestMatchersTests { @Bean @Order(Ordered.HIGHEST_PRECEDENCE) - SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); + SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(mvcMatcherBuilder.pattern("/test-1")) - .requestMatchers(mvcMatcherBuilder.pattern("/test-2")) - .requestMatchers(mvcMatcherBuilder.pattern("/test-3"))) + .requestMatchers(builder.matcher("/test-1")) + .requestMatchers(builder.matcher("/test-2")) + .requestMatchers(builder.matcher("/test-3"))) .authorizeRequests((requests) -> requests .anyRequest().denyAll()) .httpBasic(withDefaults()); @@ -225,12 +221,11 @@ public class HttpSecurityRequestMatchersTests { } @Bean - SecurityFilterChain second(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); + SecurityFilterChain second(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(mvcMatcherBuilder.pattern("/test-1"))) + .requestMatchers(builder.matcher("/test-1"))) .authorizeRequests((requests) -> requests .anyRequest().permitAll()); // @formatter:on @@ -255,10 +250,10 @@ public class HttpSecurityRequestMatchersTests { static class MvcMatcherConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http - .securityMatcher(new MvcRequestMatcher(introspector, "/path")) + .securityMatcher(builder.matcher("/path")) .httpBasic(withDefaults()) .authorizeRequests((requests) -> requests .anyRequest().denyAll()); @@ -289,11 +284,11 @@ public class HttpSecurityRequestMatchersTests { static class RequestMatchersMvcMatcherConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(new MvcRequestMatcher(introspector, "/path"))) + .requestMatchers(builder.matcher("/path"))) .httpBasic(withDefaults()) .authorizeRequests((requests) -> requests .anyRequest().denyAll()); @@ -324,11 +319,11 @@ public class HttpSecurityRequestMatchersTests { static class RequestMatchersMvcMatcherInLambdaConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((secure) -> secure - .requestMatchers(new MvcRequestMatcher(introspector, "/path")) + .requestMatchers(builder.matcher("/path")) ) .httpBasic(withDefaults()) .authorizeRequests((authorize) -> authorize @@ -356,13 +351,11 @@ public class HttpSecurityRequestMatchersTests { static class RequestMatchersMvcMatcherServeltPathConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); - mvcMatcherBuilder.servletPath("/spring"); + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(mvcMatcherBuilder.pattern("/path")) + .requestMatchers(builder.basePath("/spring").matcher("/path")) .requestMatchers("/never-match")) .httpBasic(withDefaults()) .authorizeRequests((requests) -> requests @@ -394,13 +387,11 @@ public class HttpSecurityRequestMatchersTests { static class RequestMatchersMvcMatcherServletPathInLambdaConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); - mvcMatcherBuilder.servletPath("/spring"); + SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .securityMatchers((secure) -> secure - .requestMatchers(mvcMatcherBuilder.pattern("/path")) + .requestMatchers(builder.basePath("/spring").matcher("/path")) .requestMatchers("/never-match") ) .httpBasic(withDefaults()) diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersNoMvcTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersNoMvcTests.java index 0b3cba058c..34b3d3a379 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersNoMvcTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersNoMvcTests.java @@ -37,7 +37,7 @@ import org.springframework.security.test.support.ClassPathExclusions; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.bind.annotation.RequestMapping; @@ -101,7 +101,7 @@ public class HttpSecuritySecurityMatchersNoMvcTests { .findFirst() .get(); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); - assertThat(requestMatchers).hasOnlyElementsOfType(AntPathRequestMatcher.class); + assertThat(requestMatchers).hasOnlyElementsOfType(PathPatternRequestMatcher.class); } public void loadConfig(Class... configs) { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersTests.java index 9de85b6957..29ebe34089 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersTests.java @@ -39,12 +39,11 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.servlet.MockServletContext; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.config.Customizer.withDefaults; @@ -356,14 +355,13 @@ public class HttpSecuritySecurityMatchersTests { static class SecurityMatchersMvcMatcherServletPathConfig { @Bean - SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { + PathPatternRequestMatcher.Builder spring = builder.basePath("/spring"); // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(mvcMatcherBuilder.pattern("/path")) - .requestMatchers(mvcMatcherBuilder.pattern("/never-match")) + .requestMatchers(spring.matcher("/path")) + .requestMatchers(spring.matcher("/never-match")) ) .httpBasic(withDefaults()) .authorizeHttpRequests((authorize) -> authorize @@ -391,14 +389,13 @@ public class HttpSecuritySecurityMatchersTests { static class SecurityMatchersMvcMatcherServletPathInLambdaConfig { @Bean - SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception { + PathPatternRequestMatcher.Builder spring = builder.basePath("/spring"); // @formatter:off http .securityMatchers((matchers) -> matchers - .requestMatchers(mvcMatcherBuilder.pattern("/path")) - .requestMatchers(mvcMatcherBuilder.pattern("/never-match")) + .requestMatchers(spring.matcher("/path")) + .requestMatchers(spring.matcher("/never-match")) ) .httpBasic(withDefaults()) .authorizeHttpRequests((authorize) -> authorize diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpsRedirectConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpsRedirectConfigurerTests.java index 944f21203a..dbb174ead9 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpsRedirectConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpsRedirectConfigurerTests.java @@ -126,11 +126,6 @@ public class HttpsRedirectConfigurerTests { return http.build(); } - @Bean - PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() { - return new PathPatternRequestMatcherBuilderFactoryBean(); - } - } @Configuration diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java index 0d02e44132..0831bdc7ce 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java @@ -43,7 +43,6 @@ import org.springframework.security.web.authentication.RememberMeServices; import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -349,7 +348,7 @@ public class NamespaceRememberMeTests { SecurityFilterChain withoutKeyFilterChain(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatcher(new AntPathRequestMatcher("/without-key/**")) + .securityMatcher("/without-key/**") .authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated()) .formLogin((login) -> login .loginProcessingUrl("/without-key/login")) diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java index 5155d32a45..7b0c83b032 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java @@ -34,7 +34,6 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.config.test.SpringTestContextExtension; -import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; import org.springframework.security.core.userdetails.User; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.test.web.servlet.RequestCacheResultMatcher; @@ -502,11 +501,6 @@ public class RequestCacheConfigurerTests { @EnableWebSecurity static class PathPatternFactoryBeanConfig { - @Bean - PathPatternRequestMatcherBuilderFactoryBean factoryBean() { - return new PathPatternRequestMatcherBuilderFactoryBean(); - } - } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java index d28dca2d42..885ba9f5bd 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java @@ -27,9 +27,9 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.config.test.SpringTestContextExtension; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -79,9 +79,9 @@ public class RequestMatcherConfigurerTests { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(new AntPathRequestMatcher("/api/**"))) + .requestMatchers(pathPattern("/api/**"))) .securityMatchers((security) -> security - .requestMatchers(new AntPathRequestMatcher("/oauth/**"))) + .requestMatchers(pathPattern("/oauth/**"))) .authorizeRequests((requests) -> requests .anyRequest().denyAll()); return http.build(); @@ -99,10 +99,10 @@ public class RequestMatcherConfigurerTests { // @formatter:off http .securityMatchers((secure) -> secure - .requestMatchers(new AntPathRequestMatcher("/api/**")) + .requestMatchers(pathPattern("/api/**")) ) .securityMatchers((securityMatchers) -> securityMatchers - .requestMatchers(new AntPathRequestMatcher("/oauth/**")) + .requestMatchers(pathPattern("/oauth/**")) ) .authorizeRequests((authorize) -> authorize .anyRequest().denyAll() diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java index d0728428dc..b43ffd8831 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java @@ -41,12 +41,11 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.servlet.MockServletContext; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.config.Customizer.withDefaults; @@ -133,12 +132,12 @@ public class UrlAuthorizationConfigurerTests { @Bean SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context, - HandlerMappingIntrospector introspector) throws Exception { + PathPatternRequestMatcher.Builder builder) throws Exception { // @formatter:off http .httpBasic(withDefaults()) .apply(new UrlAuthorizationConfigurer(context)).getRegistry() - .requestMatchers(new MvcRequestMatcher(introspector, "/path")).hasRole("ADMIN"); + .requestMatchers(builder.matcher("/path")).hasRole("ADMIN"); // @formatter:on return http.build(); } @@ -167,14 +166,13 @@ public class UrlAuthorizationConfigurerTests { @Bean SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context, - HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher mvcRequestMatcher = new MvcRequestMatcher(introspector, "/path"); - mvcRequestMatcher.setServletPath("/spring"); + PathPatternRequestMatcher.Builder builder) throws Exception { + PathPatternRequestMatcher.Builder spring = builder.basePath("/spring"); // @formatter:off http .httpBasic(withDefaults()) .apply(new UrlAuthorizationConfigurer(context)).getRegistry() - .requestMatchers(mvcRequestMatcher).hasRole("ADMIN"); + .requestMatchers(builder.matcher("/path")).hasRole("ADMIN"); // @formatter:on return http.build(); } diff --git a/config/src/test/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHintsTests.java b/config/src/test/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHintsTests.java index 906deec0e9..57f9a82750 100644 --- a/config/src/test/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHintsTests.java +++ b/config/src/test/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHintsTests.java @@ -53,12 +53,4 @@ class WebMvcSecurityConfigurationRuntimeHintsTests { .withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.hints); } - @Test - void handlerMappingIntrospectorCacheFilterFactoryBeanHasHints() { - assertThat(RuntimeHintsPredicates.reflection() - .onType(TypeReference - .of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean")) - .withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.hints); - } - } diff --git a/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java b/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java index d75ce815d5..48568cbf04 100644 --- a/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java +++ b/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java @@ -44,7 +44,7 @@ import org.springframework.security.web.access.intercept.FilterInvocationSecurit import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.test.util.ReflectionTestUtils; @@ -144,12 +144,13 @@ public class DefaultFilterChainValidatorTests { @Test void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() { + PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults(); AnonymousAuthenticationFilter authenticationFilter = mock(AnonymousAuthenticationFilter.class); ExceptionTranslationFilter exceptionTranslationFilter = mock(ExceptionTranslationFilter.class); - SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"), - authenticationFilter, exceptionTranslationFilter, this.authorizationInterceptor); - SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"), - authenticationFilter, exceptionTranslationFilter, this.authorizationInterceptor); + SecurityFilterChain chain1 = new DefaultSecurityFilterChain(builder.matcher("/api"), authenticationFilter, + exceptionTranslationFilter, this.authorizationInterceptor); + SecurityFilterChain chain2 = new DefaultSecurityFilterChain(builder.matcher("/api"), authenticationFilter, + exceptionTranslationFilter, this.authorizationInterceptor); List chains = new ArrayList<>(); chains.add(chain2); chains.add(chain1); diff --git a/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java index 2567471afd..5bd2d50f7a 100644 --- a/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java @@ -92,12 +92,10 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests { public void interceptUrlsSupportPropertyPlaceholders() { System.setProperty("secure.url", "/secure"); System.setProperty("secure.role", "ROLE_A"); - setContext( - "" - + "" - + "" - + " " - + ""); + setContext("" + + "" + + " " + + ""); DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) this.appContext .getBean("fids"); Collection cad = fids.getAttributes(createFilterInvocation("/secure", "GET")); @@ -107,8 +105,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests { @Test public void parsingWithinFilterSecurityInterceptorIsSuccessful() { // @formatter:off - setContext("" + - "" + setContext("" + "" + " " + " " diff --git a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java index 9088bb443f..0665978b43 100644 --- a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java @@ -72,7 +72,7 @@ public class FormLoginConfigTests { @Test public void getProtectedPageWhenFormLoginConfiguredThenRedirectsToDefaultLoginPage() throws Exception { - this.spring.configLocations(this.xml("WithAntRequestMatcher")).autowire(); + this.spring.configLocations(this.xml("WithRequestMatcher")).autowire(); // @formatter:off this.mvc.perform(get("/")) .andExpect(redirectedUrl("http://localhost/login")); diff --git a/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java b/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java index f0f983022f..69245d6bac 100644 --- a/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.stubbing.Answer; -import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.mock.web.MockServletContext; @@ -38,7 +37,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.ConfigurableWebApplicationContext; import org.springframework.web.util.WebUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -250,21 +248,6 @@ public class InterceptUrlConfigTests { assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull(); } - @Test - public void requestWhenUsingMvcMatchersThenAuthorizesRequestsAccordingly() throws Exception { - this.spring.configLocations(this.xml("MvcMatchers")).autowire(); - this.mvc.perform(get("/path")).andExpect(status().isUnauthorized()); - } - - @Test - public void requestWhenUsingMvcMatchersAndAuthorizationManagerThenAuthorizesRequestsAccordingly() throws Exception { - this.spring.configLocations(this.xml("MvcMatchersAuthorizationManager")).autowire(); - this.mvc.perform(get("/path")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/path.html")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/path/")).andExpect(status().isUnauthorized()); - assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull(); - } - @Test public void requestWhenUsingMvcMatchersAndPathVariablesThenAuthorizesRequestsAccordingly() throws Exception { this.spring.configLocations(this.xml("MvcMatchersPathVariables")).autowire(); @@ -293,48 +276,6 @@ public class InterceptUrlConfigTests { assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull(); } - @Test - public void requestWhenUsingMvcMatchersAndServletPathThenAuthorizesRequestsAccordingly() throws Exception { - this.spring.configLocations(this.xml("MvcMatchersServletPath")).autowire(); - MockServletContext servletContext = mockServletContext("/spring"); - ConfigurableWebApplicationContext context = this.spring.getContext(); - context.setServletContext(servletContext); - // @formatter:off - this.mvc.perform(get("/spring/path").servletPath("/spring")) - .andExpect(status().isUnauthorized()); - // @formatter:on - } - - @Test - public void requestWhenUsingMvcMatchersAndServletPathAndAuthorizationManagerThenAuthorizesRequestsAccordingly() - throws Exception { - this.spring.configLocations(this.xml("MvcMatchersServletPathAuthorizationManager")).autowire(); - MockServletContext servletContext = mockServletContext("/spring"); - ConfigurableWebApplicationContext context = this.spring.getContext(); - context.setServletContext(servletContext); - // @formatter:off - this.mvc.perform(get("/spring/path").servletPath("/spring")) - .andExpect(status().isUnauthorized()); - this.mvc.perform(get("/spring/path.html").servletPath("/spring")) - .andExpect(status().isUnauthorized()); - this.mvc.perform(get("/spring/path/").servletPath("/spring")) - .andExpect(status().isUnauthorized()); - // @formatter:on - assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull(); - } - - @Test - public void configureWhenUsingAntMatcherAndServletPathThenThrowsException() { - assertThatExceptionOfType(BeanDefinitionParsingException.class) - .isThrownBy(() -> this.spring.configLocations(this.xml("AntMatcherServletPath")).autowire()); - } - - @Test - public void configureWhenUsingAntMatcherAndServletPathAndAuthorizationManagerThenThrowsException() { - assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy( - () -> this.spring.configLocations(this.xml("AntMatcherServletPathAuthorizationManager")).autowire()); - } - @Test public void configureWhenUsingRegexMatcherAndServletPathThenThrowsException() { assertThatExceptionOfType(BeanDefinitionParsingException.class) @@ -366,12 +307,6 @@ public class InterceptUrlConfigTests { .isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherServletPath")).autowire()); } - @Test - public void configureWhenUsingDefaultMatcherAndNoIntrospectorBeanThenException() { - assertThatExceptionOfType(BeanCreationException.class) - .isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherNoIntrospectorBean")).autowire()); - } - @Test public void configureWhenUsingDefaultMatcherAndServletPathAndAuthorizationManagerThenNoException() { assertThatNoException() diff --git a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java index 1c2ca465fa..f890ba85f3 100644 --- a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java +++ b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java @@ -22,7 +22,8 @@ import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer; import org.springframework.security.web.DefaultSecurityFilterChain; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern; /** * @author Rob Winch @@ -44,7 +45,7 @@ public class CustomConfigurer extends SecurityConfigurerAdapter requests - .requestMatchers(new AntPathRequestMatcher(this.permitAllPattern)).permitAll() + .requestMatchers(pathPattern(this.permitAllPattern)).permitAll() .anyRequest().authenticated()); // @formatter:on if (http.getConfigurer(FormLoginConfigurer.class) == null) { diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/CsrfDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/CsrfDslTests.kt index ae6568263d..0f23ba527b 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/CsrfDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/CsrfDslTests.kt @@ -38,12 +38,8 @@ import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequ import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy -import org.springframework.security.web.csrf.CsrfTokenRepository -import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler -import org.springframework.security.web.csrf.CsrfTokenRequestHandler -import org.springframework.security.web.csrf.DefaultCsrfToken -import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository -import org.springframework.security.web.util.matcher.AntPathRequestMatcher +import org.springframework.security.web.csrf.* +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get import org.springframework.test.web.servlet.post @@ -176,7 +172,7 @@ class CsrfDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { csrf { - requireCsrfProtectionMatcher = AntPathRequestMatcher("/test1") + requireCsrfProtectionMatcher = PathPatternRequestMatcher.pathPattern("/test1") } } return http.build() @@ -247,8 +243,8 @@ class CsrfDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { csrf { - requireCsrfProtectionMatcher = AntPathRequestMatcher("/**") - ignoringRequestMatchers(AntPathRequestMatcher("/test2")) + requireCsrfProtectionMatcher = PathPatternRequestMatcher.pathPattern("/**") + ignoringRequestMatchers(PathPatternRequestMatcher.pathPattern("/test2")) } } return http.build() @@ -279,7 +275,7 @@ class CsrfDslTests { open fun filterChain(http: HttpSecurity): SecurityFilterChain { http { csrf { - requireCsrfProtectionMatcher = AntPathRequestMatcher("/**") + requireCsrfProtectionMatcher = PathPatternRequestMatcher.pathPattern("/**") ignoringRequestMatchers("/test2") } } diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/ExceptionHandlingDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/ExceptionHandlingDslTests.kt index ed3e409cff..8d99a850df 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/ExceptionHandlingDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/ExceptionHandlingDslTests.kt @@ -32,7 +32,7 @@ import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequ import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.access.AccessDeniedHandlerImpl import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint -import org.springframework.security.web.util.matcher.AntPathRequestMatcher +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get import org.springframework.web.servlet.config.annotation.EnableWebMvc @@ -195,6 +195,7 @@ class ExceptionHandlingDslTests { customAccessDeniedHandler1.setErrorPage("/access-denied1") val customAccessDeniedHandler2 = AccessDeniedHandlerImpl() customAccessDeniedHandler2.setErrorPage("/access-denied2") + val builder = PathPatternRequestMatcher.withDefaults() http { authorizeRequests { authorize("/admin1", hasAuthority("ROLE_ADMIN")) @@ -202,8 +203,8 @@ class ExceptionHandlingDslTests { authorize(anyRequest, authenticated) } exceptionHandling { - defaultAccessDeniedHandlerFor(customAccessDeniedHandler1, AntPathRequestMatcher("/admin1")) - defaultAccessDeniedHandlerFor(customAccessDeniedHandler2, AntPathRequestMatcher("/admin2")) + defaultAccessDeniedHandlerFor(customAccessDeniedHandler1, builder.matcher("/admin1")) + defaultAccessDeniedHandlerFor(customAccessDeniedHandler2, builder.matcher("/admin2")) } } return http.build() @@ -264,13 +265,14 @@ class ExceptionHandlingDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { val customAuthenticationEntryPoint1 = LoginUrlAuthenticationEntryPoint("/custom-login1") val customAuthenticationEntryPoint2 = LoginUrlAuthenticationEntryPoint("/custom-login2") + val builder = PathPatternRequestMatcher.withDefaults(); http { authorizeRequests { authorize(anyRequest, authenticated) } exceptionHandling { - defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint1, AntPathRequestMatcher("/secured1")) - defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint2, AntPathRequestMatcher("/secured2")) + defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint1, builder.matcher("/secured1")) + defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint2, builder.matcher("/secured2")) } } return http.build() diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/LogoutDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/LogoutDslTests.kt index 7697ca4d67..0be358fdb8 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/LogoutDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/LogoutDslTests.kt @@ -40,7 +40,7 @@ import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.logout.LogoutHandler import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler import org.springframework.security.web.context.HttpSessionSecurityContextRepository -import org.springframework.security.web.util.matcher.AntPathRequestMatcher +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.post @@ -102,7 +102,7 @@ class LogoutDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { logout { - logoutRequestMatcher = AntPathRequestMatcher("/custom/logout") + logoutRequestMatcher = PathPatternRequestMatcher.pathPattern("/custom/logout") } } return http.build() @@ -307,8 +307,9 @@ class LogoutDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { logout { - logoutRequestMatcher = AntPathRequestMatcher("/logout/**") - defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(), AntPathRequestMatcher("/logout/custom")) + logoutRequestMatcher = PathPatternRequestMatcher.pathPattern("/logout/**") + defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(), + PathPatternRequestMatcher.pathPattern("/logout/custom")) } } return http.build() diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/RememberMeDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/RememberMeDslTests.kt index b73b41f50d..011547f74e 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/RememberMeDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/RememberMeDslTests.kt @@ -51,7 +51,6 @@ import org.springframework.security.web.authentication.RememberMeServices import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository -import org.springframework.security.web.util.matcher.AntPathRequestMatcher import org.springframework.test.web.servlet.MockHttpServletRequestDsl import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get @@ -472,7 +471,7 @@ internal class RememberMeDslTests { @Order(0) open fun securityFilterChainWithoutKey(http: HttpSecurity): SecurityFilterChain { http { - securityMatcher(AntPathRequestMatcher("/without-key/**")) + securityMatcher("/without-key/**") formLogin { loginProcessingUrl = "/without-key/login" } diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/headers/HttpStrictTransportSecurityDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/headers/HttpStrictTransportSecurityDslTests.kt index 3edda23411..55c120d82a 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/headers/HttpStrictTransportSecurityDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/headers/HttpStrictTransportSecurityDslTests.kt @@ -29,7 +29,7 @@ import org.springframework.security.config.test.SpringTestContext import org.springframework.security.config.test.SpringTestContextExtension import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.server.header.StrictTransportSecurityServerHttpHeadersWriter -import org.springframework.security.web.util.matcher.AntPathRequestMatcher +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get @@ -148,7 +148,7 @@ class HttpStrictTransportSecurityDslTests { headers { defaultsDisabled = true httpStrictTransportSecurity { - requestMatcher = AntPathRequestMatcher("/secure/**") + requestMatcher = PathPatternRequestMatcher.pathPattern("/secure/**") } } } diff --git a/config/src/test/resources/org/springframework/security/config/http/CsrfBeanDefinitionParserTests-RegisterDataValueProcessorOnyIfNotRegistered.xml b/config/src/test/resources/org/springframework/security/config/http/CsrfBeanDefinitionParserTests-RegisterDataValueProcessorOnyIfNotRegistered.xml index 38a8cbfc8c..0db156a6a5 100644 --- a/config/src/test/resources/org/springframework/security/config/http/CsrfBeanDefinitionParserTests-RegisterDataValueProcessorOnyIfNotRegistered.xml +++ b/config/src/test/resources/org/springframework/security/config/http/CsrfBeanDefinitionParserTests-RegisterDataValueProcessorOnyIfNotRegistered.xml @@ -15,16 +15,12 @@ --> + xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd + + + +http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd"> @@ -43,7 +39,5 @@ http://www.springframework.org/schema/security https://www.springframework.org/s - - diff --git a/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml b/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml index 5f29d2e71a..ba880a02e9 100644 --- a/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml +++ b/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml @@ -30,7 +30,6 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithAntRequestMatcher.xml b/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithRequestMatcher.xml similarity index 92% rename from config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithAntRequestMatcher.xml rename to config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithRequestMatcher.xml index b1fa269cf8..917656f861 100644 --- a/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithAntRequestMatcher.xml +++ b/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithRequestMatcher.xml @@ -24,7 +24,7 @@ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + diff --git a/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithSuccessAndFailureHandlers.xml b/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithSuccessAndFailureHandlers.xml index 63ba250e94..c88cbc620f 100644 --- a/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithSuccessAndFailureHandlers.xml +++ b/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-WithSuccessAndFailureHandlers.xml @@ -24,7 +24,7 @@ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + diff --git a/config/src/test/resources/org/springframework/security/config/http/HttpInterceptUrlTests-interceptUrlWhenRequestMatcherRefThenWorks.xml b/config/src/test/resources/org/springframework/security/config/http/HttpInterceptUrlTests-interceptUrlWhenRequestMatcherRefThenWorks.xml index 6bb85a6b92..469df9964a 100644 --- a/config/src/test/resources/org/springframework/security/config/http/HttpInterceptUrlTests-interceptUrlWhenRequestMatcherRefThenWorks.xml +++ b/config/src/test/resources/org/springframework/security/config/http/HttpInterceptUrlTests-interceptUrlWhenRequestMatcherRefThenWorks.xml @@ -16,8 +16,10 @@ - + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AuthorizationManagerFilterAllDispatcherTypes.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AuthorizationManagerFilterAllDispatcherTypes.xml index aefa2c96a4..01d7e07a44 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AuthorizationManagerFilterAllDispatcherTypes.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AuthorizationManagerFilterAllDispatcherTypes.xml @@ -33,15 +33,15 @@ - + - - + + - + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml index 75e70f4d73..367577e534 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariablesAuthorizationManager.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariablesAuthorizationManager.xml index b0c837f42d..60b7a4270a 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariablesAuthorizationManager.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariablesAuthorizationManager.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml index 3149fb4876..a54130b781 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml @@ -30,5 +30,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPathAuthorizationManager.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPathAuthorizationManager.xml index 9044cf02e1..a33e0d600e 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPathAuthorizationManager.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPathAuthorizationManager.xml @@ -30,5 +30,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-FilterAllDispatcherTypesFalse.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-FilterAllDispatcherTypesFalse.xml index 9cc9f57a58..f3c09d2a9d 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-FilterAllDispatcherTypesFalse.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-FilterAllDispatcherTypesFalse.xml @@ -33,15 +33,15 @@ - + - - + + - + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml index 03cdff6a8a..70e8f66bca 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethodAuthorizationManager.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethodAuthorizationManager.xml index 9b8b31c49a..c902554a23 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethodAuthorizationManager.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethodAuthorizationManager.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml index 862f7d99a8..9a1006fb13 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariablesAuthorizationManager.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariablesAuthorizationManager.xml index 17e62ece6a..4e52d3dd68 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariablesAuthorizationManager.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariablesAuthorizationManager.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml index ffff9b3032..3a2d320b3b 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml @@ -34,5 +34,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256AuthorizationManager.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256AuthorizationManager.xml index 31b3400262..fdfd80cae6 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256AuthorizationManager.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256AuthorizationManager.xml @@ -34,5 +34,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml index e15c53e7e8..fcb7a2d588 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml @@ -34,5 +34,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariablesAuthorizationManager.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariablesAuthorizationManager.xml index a3886876c8..ca15115024 100644 --- a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariablesAuthorizationManager.xml +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariablesAuthorizationManager.xml @@ -34,5 +34,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousDisabled.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousDisabled.xml index 37262122d5..a4a2d8d9ee 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousDisabled.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousDisabled.xml @@ -32,5 +32,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousEndpoints.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousEndpoints.xml index 8beeec94a1..dfcf559d90 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousEndpoints.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-AnonymousEndpoints.xml @@ -31,5 +31,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomHttpBasicEntryPointRef.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomHttpBasicEntryPointRef.xml index 8168a807e9..194b2d8907 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomHttpBasicEntryPointRef.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomHttpBasicEntryPointRef.xml @@ -34,5 +34,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomRequestMatcher.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomRequestMatcher.xml index b03b8d7ee9..d54f58d917 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomRequestMatcher.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-CustomRequestMatcher.xml @@ -32,7 +32,7 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-NoSecurityForPattern.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-NoSecurityForPattern.xml index d8e1e7511e..befcf14057 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-NoSecurityForPattern.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-NoSecurityForPattern.xml @@ -29,5 +29,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequest.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequest.xml index dfecf7ebe8..35aec9290c 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequest.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequest.xml @@ -31,5 +31,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequestTrue.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequestTrue.xml index 47787c9c84..d49c7cf116 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequestTrue.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-OncePerRequestTrue.xml @@ -31,5 +31,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPage.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPage.xml index c05b23c20a..63db2e1375 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPage.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPage.xml @@ -30,5 +30,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPageAuthorizationManager.xml b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPageAuthorizationManager.xml index 4d93a59162..6065ac20d0 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPageAuthorizationManager.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-ProtectedLoginPageAuthorizationManager.xml @@ -30,5 +30,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-DistinctHttpElements.xml b/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-DistinctHttpElements.xml index e1bc1587af..8d9a7a2cc5 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-DistinctHttpElements.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-DistinctHttpElements.xml @@ -35,5 +35,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-IdenticallyPatternedHttpElements.xml b/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-IdenticallyPatternedHttpElements.xml index b41948934f..e3e75d034e 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-IdenticallyPatternedHttpElements.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-IdenticallyPatternedHttpElements.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-Sec1937.xml b/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-Sec1937.xml index ec034128a5..b22b03b292 100644 --- a/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-Sec1937.xml +++ b/config/src/test/resources/org/springframework/security/config/http/MultiHttpBlockConfigTests-Sec1937.xml @@ -50,5 +50,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPage.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPage.xml index d801c8c663..aaf9b7bd3d 100644 --- a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPage.xml +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPage.xml @@ -34,5 +34,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPageWithSpEL.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPageWithSpEL.xml index 005331dc00..6217013bc3 100644 --- a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPageWithSpEL.xml +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPageWithSpEL.xml @@ -34,5 +34,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLogin.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLogin.xml index b9280474ca..9942d3e125 100644 --- a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLogin.xml +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLogin.xml @@ -39,5 +39,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLoginWithSpEL.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLoginWithSpEL.xml index ebd0289e71..fabefa4147 100644 --- a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLoginWithSpEL.xml +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLoginWithSpEL.xml @@ -42,5 +42,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-PortMapping.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-PortMapping.xml index e1380cf22e..a1c04301fd 100644 --- a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-PortMapping.xml +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-PortMapping.xml @@ -38,5 +38,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-RequiresChannel.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-RequiresChannel.xml index 167abb9989..bf0fd9cfe0 100644 --- a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-RequiresChannel.xml +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-RequiresChannel.xml @@ -33,5 +33,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-UnsecuredPattern.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-UnsecuredPattern.xml index 2fbf13881f..8d7cea147b 100644 --- a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-UnsecuredPattern.xml +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-UnsecuredPattern.xml @@ -35,5 +35,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-DefaultConfig.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-DefaultConfig.xml index e9e1ea4e21..e1e5343178 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-DefaultConfig.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-DefaultConfig.xml @@ -34,5 +34,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidity.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidity.xml index 738a9f42f8..e7e95b036e 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidity.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidity.xml @@ -36,5 +36,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec1827.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec1827.xml index 78b86e2a1e..42169c3278 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec1827.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec1827.xml @@ -36,5 +36,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec2165.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec2165.xml index 2d717a4496..1af805ce8c 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec2165.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec2165.xml @@ -36,5 +36,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec742.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec742.xml index 51e79b3283..e39fc15893 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec742.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec742.xml @@ -37,5 +37,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-SecureCookie.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-SecureCookie.xml index faeeddcedc..4ec93b0833 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-SecureCookie.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-SecureCookie.xml @@ -36,5 +36,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-TokenValidity.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-TokenValidity.xml index 6042ea290e..e5ddf8bf65 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-TokenValidity.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-TokenValidity.xml @@ -36,5 +36,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithAuthenticationSuccessHandler.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithAuthenticationSuccessHandler.xml index f66b683c46..d15c6be3a8 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithAuthenticationSuccessHandler.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithAuthenticationSuccessHandler.xml @@ -43,5 +43,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithDataSource.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithDataSource.xml index 0677224c0e..6dc53c5440 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithDataSource.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithDataSource.xml @@ -38,5 +38,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookie.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookie.xml index 5dbfac6d8f..151b6d674b 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookie.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookie.xml @@ -30,5 +30,4 @@ - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameter.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameter.xml index c3f2cb9574..70a56b60a8 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameter.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameter.xml @@ -34,5 +34,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithSecurityContextHolderStrategy.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithSecurityContextHolderStrategy.xml index 369a5e1417..678f7937fc 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithSecurityContextHolderStrategy.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithSecurityContextHolderStrategy.xml @@ -40,5 +40,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithServicesRef.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithServicesRef.xml index e6e11567ab..c9c292feaf 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithServicesRef.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithServicesRef.xml @@ -44,5 +44,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithTokenRepository.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithTokenRepository.xml index 520c9a142d..dbb2a58687 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithTokenRepository.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithTokenRepository.xml @@ -48,5 +48,4 @@ class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithUserDetailsService.xml b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithUserDetailsService.xml index 457f9807ee..6dc89e2c9d 100644 --- a/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithUserDetailsService.xml +++ b/config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithUserDetailsService.xml @@ -41,5 +41,4 @@ name="basicController" class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests-MultiHttp.xml b/config/src/test/resources/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests-MultiHttp.xml index 1b9bff3c77..b3b374ace9 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests-MultiHttp.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests-MultiHttp.xml @@ -55,6 +55,5 @@ - - + diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionIfRequired.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionIfRequired.xml index f659f8841a..34b1fb5bdc 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionIfRequired.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionIfRequired.xml @@ -33,5 +33,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionNever.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionNever.xml index 45280f776e..e1deb04064 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionNever.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionNever.xml @@ -33,5 +33,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionStateless.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionStateless.xml index 968c474575..bb68e03dc2 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionStateless.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-CreateSessionStateless.xml @@ -33,5 +33,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-NoSessionManagementFilter.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-NoSessionManagementFilter.xml index 92ec3ae9c2..98431bdc08 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-NoSessionManagementFilter.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-NoSessionManagementFilter.xml @@ -34,5 +34,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec1208.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec1208.xml index 8cd46c54a2..75a57186c3 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec1208.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec1208.xml @@ -37,5 +37,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec2137.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec2137.xml index 604b4fea11..d72cd00f3d 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec2137.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec2137.xml @@ -35,5 +35,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionAuthenticationStrategyRef.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionAuthenticationStrategyRef.xml index a84edef1dc..74c2ae3ac8 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionAuthenticationStrategyRef.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionAuthenticationStrategyRef.xml @@ -38,5 +38,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.TeapotSessionAuthenticationStrategy"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionMigrateSession.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionMigrateSession.xml index 9e4deb3fa1..5ff8a87363 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionMigrateSession.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionMigrateSession.xml @@ -35,5 +35,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNone.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNone.xml index 62a808bafa..f44ea0f70c 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNone.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNone.xml @@ -33,5 +33,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNoneWithInvalidSessionUrl.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNoneWithInvalidSessionUrl.xml index 394b28eef1..daa46c831f 100644 --- a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNoneWithInvalidSessionUrl.xml +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionNoneWithInvalidSessionUrl.xml @@ -33,5 +33,4 @@ class="org.springframework.security.config.http.SessionManagementConfigTests.BasicController"/> - diff --git a/config/src/test/resources/org/springframework/security/config/http/handlermappingintrospector.xml b/config/src/test/resources/org/springframework/security/config/http/handlermappingintrospector.xml deleted file mode 100644 index 2b730a2465..0000000000 --- a/config/src/test/resources/org/springframework/security/config/http/handlermappingintrospector.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - diff --git a/config/src/test/resources/org/springframework/security/util/filtertest-valid.xml b/config/src/test/resources/org/springframework/security/util/filtertest-valid.xml index d12165a7b4..e40f1e9426 100644 --- a/config/src/test/resources/org/springframework/security/util/filtertest-valid.xml +++ b/config/src/test/resources/org/springframework/security/util/filtertest-valid.xml @@ -45,7 +45,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -149,7 +149,7 @@ - + @@ -159,7 +159,7 @@ - + @@ -174,7 +174,5 @@ - - diff --git a/web/src/main/java/org/springframework/security/web/FilterChainProxy.java b/web/src/main/java/org/springframework/security/web/FilterChainProxy.java index c71ea74930..46ce8d11b3 100644 --- a/web/src/main/java/org/springframework/security/web/FilterChainProxy.java +++ b/web/src/main/java/org/springframework/security/web/FilterChainProxy.java @@ -34,6 +34,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.core.log.LogMessage; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolderStrategy; +import org.springframework.security.web.access.PathPatternRequestTransformer; import org.springframework.security.web.firewall.FirewalledRequest; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler; @@ -258,7 +259,9 @@ public class FilterChainProxy extends GenericFilterBean { * @return matching filter list */ public List getFilters(String url) { - return getFilters(this.firewall.getFirewalledRequest(new FilterInvocation(url, "GET").getRequest())); + PathPatternRequestTransformer requestTransformer = new PathPatternRequestTransformer(); + HttpServletRequest transformed = requestTransformer.transform(new FilterInvocation(url, "GET").getRequest()); + return getFilters(this.firewall.getFirewalledRequest(transformed)); } /** diff --git a/web/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java b/web/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java index db0f11ea60..d7954abdf0 100644 --- a/web/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java +++ b/web/src/main/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSource.java @@ -86,7 +86,7 @@ public class DefaultFilterInvocationSecurityMetadataSource implements FilterInvo @Override public Collection getAttributes(Object object) { - final HttpServletRequest request = ((FilterInvocation) object).getRequest(); + final HttpServletRequest request = getHttpServletRequest(object); int count = 0; for (Map.Entry> entry : this.requestMap.entrySet()) { if (entry.getKey().matches(request)) { @@ -107,4 +107,14 @@ public class DefaultFilterInvocationSecurityMetadataSource implements FilterInvo return FilterInvocation.class.isAssignableFrom(clazz); } + private HttpServletRequest getHttpServletRequest(Object object) { + if (object instanceof FilterInvocation invocation) { + return invocation.getHttpRequest(); + } + if (object instanceof HttpServletRequest request) { + return request; + } + throw new IllegalArgumentException("object must be of type FilterInvocation or HttpServletRequest"); + } + }