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"); + } + }