diff --git a/cas/spring-security-cas.gradle b/cas/spring-security-cas.gradle index cc5c13f6047..fd4a614fa56 100644 --- a/cas/spring-security-cas.gradle +++ b/cas/spring-security-cas.gradle @@ -14,6 +14,7 @@ dependencies { provided 'jakarta.servlet:jakarta.servlet-api' + testImplementation project(path : ':spring-security-web', configuration : 'tests') testImplementation "org.assertj:assertj-core" testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-params" diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java index 43283b7ccf6..0e7ff836c0f 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java +++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java @@ -52,7 +52,6 @@ import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.SavedRequest; 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; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -335,7 +334,7 @@ public final void setProxyReceptorMatcher(RequestMatcher proxyReceptorMatcher) { } public final void setProxyReceptorUrl(final String proxyReceptorUrl) { - this.proxyReceptorMatcher = new AntPathRequestMatcher("/**" + proxyReceptorUrl); + this.proxyReceptorMatcher = PathPatternRequestMatcher.withDefaults().matcher(proxyReceptorUrl); } public final void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) { diff --git a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java index 296043527e6..423c99cfe5f 100644 --- a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java +++ b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java @@ -55,6 +55,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * Tests {@link CasAuthenticationFilter}. @@ -79,9 +81,7 @@ public void testGettersSetters() { @Test public void testNormalOperation() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login/cas"); - request.setServletPath("/login/cas"); - request.addParameter("ticket", "ST-0-ER94xMJmn6pha35CQRoZ"); + MockHttpServletRequest request = post("/login/cas").param("ticket", "ST-0-ER94xMJmn6pha35CQRoZ").build(); CasAuthenticationFilter filter = new CasAuthenticationFilter(); filter.setAuthenticationManager((a) -> a); assertThat(filter.requiresAuthentication(request, new MockHttpServletResponse())).isTrue(); @@ -104,24 +104,22 @@ public void testRequiresAuthenticationFilterProcessUrl() { String url = "/login/cas"; CasAuthenticationFilter filter = new CasAuthenticationFilter(); filter.setFilterProcessesUrl(url); - MockHttpServletRequest request = new MockHttpServletRequest("POST", url); + MockHttpServletRequest request = post(url).build(); MockHttpServletResponse response = new MockHttpServletResponse(); - request.setServletPath(url); assertThat(filter.requiresAuthentication(request, response)).isTrue(); } @Test public void testRequiresAuthenticationProxyRequest() { CasAuthenticationFilter filter = new CasAuthenticationFilter(); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/pgtCallback").build(); MockHttpServletResponse response = new MockHttpServletResponse(); - request.setServletPath("/pgtCallback"); assertThat(filter.requiresAuthentication(request, response)).isFalse(); filter.setProxyReceptorUrl(request.getServletPath()); assertThat(filter.requiresAuthentication(request, response)).isFalse(); filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class)); assertThat(filter.requiresAuthentication(request, response)).isTrue(); - request.setServletPath("/other"); + request = get("/other").build(); assertThat(filter.requiresAuthentication(request, response)).isFalse(); } @@ -133,12 +131,10 @@ public void testRequiresAuthenticationAuthAll() { CasAuthenticationFilter filter = new CasAuthenticationFilter(); filter.setFilterProcessesUrl(url); filter.setServiceProperties(properties); - MockHttpServletRequest request = new MockHttpServletRequest("POST", url); + MockHttpServletRequest request = post(url).build(); MockHttpServletResponse response = new MockHttpServletResponse(); - request.setServletPath(url); assertThat(filter.requiresAuthentication(request, response)).isTrue(); - request = new MockHttpServletRequest("POST", "/other"); - request.setServletPath("/other"); + request = post("/other").build(); assertThat(filter.requiresAuthentication(request, response)).isFalse(); request.setParameter(properties.getArtifactParameter(), "value"); assertThat(filter.requiresAuthentication(request, response)).isTrue(); @@ -156,9 +152,8 @@ public void testRequiresAuthenticationAuthAll() { @Test public void testAuthenticateProxyUrl() throws Exception { CasAuthenticationFilter filter = new CasAuthenticationFilter(); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/pgtCallback").build(); MockHttpServletResponse response = new MockHttpServletResponse(); - request.setServletPath("/pgtCallback"); filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class)); filter.setProxyReceptorUrl(request.getServletPath()); assertThat(filter.attemptAuthentication(request, response)).isNull(); @@ -172,9 +167,7 @@ public void testDoFilterAuthenticateAll() throws Exception { given(manager.authenticate(any(Authentication.class))).willReturn(authentication); ServiceProperties serviceProperties = new ServiceProperties(); serviceProperties.setAuthenticateAllArtifacts(true); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/authenticate"); - request.setParameter("ticket", "ST-1-123"); - request.setServletPath("/authenticate"); + MockHttpServletRequest request = post("/authenticate").param("ticket", "ST-1-123").build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); CasAuthenticationFilter filter = new CasAuthenticationFilter(); @@ -200,10 +193,9 @@ public void testDoFilterAuthenticateAll() throws Exception { @Test public void testChainNotInvokedForProxyReceptor() throws Exception { CasAuthenticationFilter filter = new CasAuthenticationFilter(); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/pgtCallback").build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); - request.setServletPath("/pgtCallback"); filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class)); filter.setProxyReceptorUrl(request.getServletPath()); filter.doFilter(request, response, chain); @@ -271,16 +263,14 @@ void successfulAuthenticationWhenSecurityContextHolderStrategySetThenUses() thro @Test public void requiresAuthenticationWhenProxyRequestMatcherThenMatches() { CasAuthenticationFilter filter = new CasAuthenticationFilter(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/pgtCallback"); + MockHttpServletRequest request = get("/pgtCallback").build(); MockHttpServletResponse response = new MockHttpServletResponse(); - request.setServletPath("/pgtCallback"); assertThat(filter.requiresAuthentication(request, response)).isFalse(); filter.setProxyReceptorMatcher(PathPatternRequestMatcher.withDefaults().matcher(request.getServletPath())); assertThat(filter.requiresAuthentication(request, response)).isFalse(); filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class)); assertThat(filter.requiresAuthentication(request, response)).isTrue(); - request.setRequestURI("/other"); - request.setServletPath("/other"); + request = get("/other").build(); assertThat(filter.requiresAuthentication(request, response)).isFalse(); } 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 4b9db8bd49c..5d2624f8e33 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 @@ 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 @@ */ 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,36 +75,6 @@ public C anyRequest() { 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 - */ - 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} @@ -180,12 +118,9 @@ public C requestMatchers(RequestMatcher... requestMatchers) { /** *

- * 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 @@ -193,8 +128,7 @@ public C requestMatchers(RequestMatcher... requestMatchers) { *

* @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 */ @@ -205,27 +139,13 @@ public C requestMatchers(HttpMethod method, String... patterns) { + "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 + .getBeanProvider(PathPatternRequestMatcher.Builder.class) + .getIfUnique(PathPatternRequestMatcher::withDefaults); 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])); } @@ -239,64 +159,16 @@ private boolean anyPathsDontStartWithLeadingSlash(String... patterns) { 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 */ @@ -306,12 +178,7 @@ public C requestMatchers(String... patterns) { /** *

- * 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 @@ -335,182 +202,4 @@ public C requestMatchers(HttpMethod method) { */ 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 index e6cca45bf12..ddf839a6e93 100644 --- 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 @@ -19,7 +19,6 @@ 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; /** @@ -34,11 +33,8 @@ 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; + builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class) + .getIfUnique(PathPatternRequestMatcher::withDefaults); } public static RequestMatcher matcher(String path) { @@ -46,10 +42,7 @@ public static RequestMatcher matcher(String 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); + return builder.matcher(method, path); } 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 1c891418242..b9ea681ec95 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.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.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.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 @@ 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> headersC /** * Adds a {@link CorsFilter} to be used. If a bean by the name of corsFilter is * provided, that {@link CorsFilter} is used. Else if corsConfigurationSource is - * defined, then that {@link CorsConfiguration} is used. Otherwise, if Spring MVC is - * on the classpath a {@link HandlerMappingIntrospector} is used. You can enable CORS - * using: + * defined, then that {@link CorsConfiguration} is used. You can enable CORS using: * *

 	 * @Configuration
@@ -2202,10 +2185,8 @@ public HttpSecurity securityMatcher(RequestMatcher requestMatcher) {
 
 	/**
 	 * Allows configuring the {@link HttpSecurity} to only be invoked when matching the
-	 * provided pattern. This method creates a {@link MvcRequestMatcher} if Spring MVC is
-	 * in the classpath or creates an {@link AntPathRequestMatcher} if not. If more
-	 * advanced configuration is necessary, consider using
-	 * {@link #securityMatchers(Customizer)} or {@link #securityMatcher(RequestMatcher)}.
+	 * provided set of {@code patterns}. See
+	 * {@link org.springframework.web.util.pattern.PathPattern} for matching rules
 	 *
 	 * 

* Invoking {@link #securityMatcher(String...)} will override previous invocations of @@ -2215,19 +2196,16 @@ public HttpSecurity securityMatcher(RequestMatcher requestMatcher) { *

* @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() + .getBeanProvider(PathPatternRequestMatcher.Builder.class) + .getIfUnique(PathPatternRequestMatcher::withDefaults); 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; @@ -2258,26 +2236,6 @@ public HttpSecurity webAuthn(Customizer> webAut return HttpSecurity.this; } - private RequestMatcher createAntMatcher(String pattern) { - return new AntPathRequestMatcher(pattern); - } - - private RequestMatcher createMvcMatcher(String mvcPattern) { - ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class, Object.class); - ObjectProvider> 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 9b906ebdfdd..729690afbb4 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.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; @@ -430,7 +431,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws this.filterChainDecoratorPostProcessor = postProcessor.getIfUnique(ObjectPostProcessor::identity); Class 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/WebMvcSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java index 73a56456d85..3e6459918c7 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.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.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.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 @@ */ 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 @@ public void setApplicationContext(ApplicationContext applicationContext) throws } } - @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 7e31a0ebf93..a3befc654f9 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 @@ -69,7 +69,6 @@ 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 @@ -209,12 +208,11 @@ public void setImportMetadata(AnnotationMetadata importMetadata) { /** * 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/CorsConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java index c35c2eb5e2f..751f1bf0bcc 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java @@ -22,18 +22,14 @@ import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.filter.CorsFilter; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; /** * Adds {@link CorsFilter} to the Spring Security filter chain. If a bean by the name of * corsFilter is provided, that {@link CorsFilter} is used. Else if * corsConfigurationSource is defined, then that {@link CorsConfiguration} is used. - * Otherwise, if Spring MVC is on the classpath a {@link HandlerMappingIntrospector} is - * used. * * @param 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 @@ private CorsFilter getCorsFilter(ApplicationContext context) { 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/RequestCacheConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java index 3be334a17df..161e8872f7a 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 @@ -31,7 +31,6 @@ 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; @@ -174,12 +173,7 @@ private RequestMatcher notMatchingMediaType(H http, MediaType mediaType) { } private RequestMatcher getFaviconRequestMatcher() { - if (RequestMatcherFactory.usesPathPatterns()) { - return RequestMatcherFactory.matcher("/favicon.*"); - } - else { - return new AntPathRequestMatcher("/**/favicon.*"); - } + return RequestMatcherFactory.matcher("/favicon.*"); } } 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 9d292b24778..18ff47e5caf 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 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) { .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 53ff1238b0e..dff1e583681 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 @@ private BeanMetadataElement createMatcher(MatcherType matcherType, Element urlEl 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 94d87300622..6410f2f2fa8 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.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 BeanMetadataElement getSource(Element element, ParserContext parserContex 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 302e95834a7..60da7445cc6 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.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 8f2baeb4c68..84c9d65e97b 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.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 @@ private void checkLoginPageIsntProtected(FilterChainProxy fcp, List filt 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 @@ private void checkLoginPageIsntProtected(FilterChainProxy fcp, List filt } } - 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 @@ private boolean checkLoginPageIsPublic(List filters, FilterInvocation lo 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 @@ private boolean checkLoginPageIsPublic(List filters, FilterInvocation lo 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 @@ private Supplier deriveAnonymousCheck(List filters, FilterInvoc 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 506aa3cd2b9..19e0502f4f1 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 @@ private static ManagedMap parseInterceptUrl 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 1b22c044f67..93e9fba462d 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 @@ -50,7 +50,6 @@ 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 +87,6 @@ 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 +98,6 @@ */ 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"; @@ -793,10 +786,8 @@ private void createAuthorizationFilter() { 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 +957,7 @@ private static BeanMetadataElement getObservationRegistry(Element httpElmt) { return BeanDefinitionBuilder.rootBeanDefinition(ObservationRegistryFactory.class).getBeanDefinition(); } - static class HandlerMappingIntrospectorRequestTransformerFactoryBean + static class PathPatternRequestTransformerFactoryBean implements FactoryBean, ApplicationContextAware { @@ -982,10 +973,7 @@ public AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTra 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 3755cb84e8e..68b1bd960fd 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,10 @@ 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.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.RegexRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; -import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** @@ -39,21 +36,12 @@ */ 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; + path(PathPatternRequestMatcher.class), regex(RegexRequestMatcher.class), ciRegex(RegexRequestMatcher.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 +54,17 @@ public BeanDefinition createMatcher(ParserContext pc, String path, String method 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 +76,10 @@ static MatcherType fromElement(Element elt) { 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 00000000000..7037bd2853d --- /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 f08a21727a6..6bb93665f7f 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.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 RequestMatcherFactoryBean(String path, HttpMethod method) { @Override public RequestMatcher getObject() throws Exception { - if (this.builder != null) { - return this.builder.matcher(this.method, this.path); - } - return new AntPathRequestMatcher(this.path, (this.method != null) ? this.method.name() : null); + return this.builder.matcher(this.method, this.path); } @Override @@ -58,7 +54,8 @@ public Class getObjectType() { @Override public void setApplicationContext(ApplicationContext context) throws BeansException { - this.builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class).getIfUnique(); + this.builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class) + .getIfUnique(PathPatternRequestMatcher::withDefaults); } } diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AbstractRequestMatcherDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AbstractRequestMatcherDsl.kt index ba0087a3aaa..eeae8941d5b 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AbstractRequestMatcherDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AbstractRequestMatcherDsl.kt @@ -58,6 +58,6 @@ abstract class AbstractRequestMatcherDsl { protected abstract class AuthorizationManagerRule(open val rule: AuthorizationManager) protected enum class PatternType { - 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 0133670a18f..5488dd0289f 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 f6891ca0ef6..2620ccbe828 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 b1246a122a0..461fe9168cd 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) 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 e57aaf19a0a..fe7f4e78dea 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 323b7853864..48433204db4 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 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 676b55a13dd..def6b638920 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,7 @@ - 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 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 e2f81e3e17d..71d879e3996 100644 --- a/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java @@ -39,11 +39,13 @@ 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; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link FilterChainProxy}. @@ -120,7 +122,7 @@ public void mixingPatternsAndPlaceholdersDoesntCauseOrderingIssues() { 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) { @@ -143,13 +145,12 @@ private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) { } private void doNormalOperation(FilterChainProxy filterChainProxy) throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setServletPath("/foo/secure/super/somefile.html"); + MockHttpServletRequest request = get("/foo/secure/super/somefile.html").build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); filterChainProxy.doFilter(request, response, chain); verify(chain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); - request.setServletPath("/a/path/which/doesnt/match/any/filter.html"); + request = get("/a/path/which/doesnt/match/any/filter.html").build(); chain = mock(FilterChain.class); filterChainProxy.doFilter(request, response, chain); verify(chain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); 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 4b338c116dc..a2b12f0a836 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,7 +32,7 @@ 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.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.util.Assert; /** @@ -52,7 +52,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests((requests) -> requests - .requestMatchers(new AntPathRequestMatcher("/*")).permitAll()) + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/*")).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 0a0b9709688..fc26059e484 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 @@ -24,12 +24,11 @@ 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.config.web.PathPatternRequestMatcherBuilderFactoryBean; 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; @@ -88,7 +87,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeRequests((requests) -> requests .anyRequest().authenticated() - .requestMatchers(new AntPathRequestMatcher("/demo/**")).permitAll()); + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/demo/**")).permitAll()); return http.build(); // @formatter:on } @@ -100,12 +99,17 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { static class MvcMatchersAfterAnyRequestConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 +160,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeRequests((requests) -> requests .anyRequest().authenticated() - .requestMatchers(new AntPathRequestMatcher("/**")).permitAll()); + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/**")).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 4d7c9a18ffe..7c943e01e65 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 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,25 @@ public class AbstractRequestMatcherRegistryNoMvcTests { @BeforeEach public void setUp() { this.matcherRegistry = new TestRequestMatcherRegistry(); + GenericApplicationContext context = new GenericApplicationContext(); + 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 +68,7 @@ public void requestMatchersWhenHttpMethodAndMvcNotPresentThenReturnAntPathMatche 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 70f383c203a..e098d11b381 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,30 @@ package org.springframework.security.config.annotation.web; -import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; 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.ArgumentMatchers.any; 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; /** * Tests for {@link AbstractRequestMatcherRegistry}. @@ -86,9 +69,13 @@ public void setUp() { 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.getBeanProvider(any(Class.class))).willReturn(new ObjectProvider<>() { + @Override + public Stream stream() { + return Stream.of(); + } + }); this.matcherRegistry.setApplicationContext(this.context); - mockMvcIntrospector(true); } @Test @@ -110,24 +97,25 @@ public void regexMatchersWhenPatternParamThenReturnRegexRequestMatcherType() { } @Test - public void antMatchersWhenHttpMethodAndPatternParamsThenReturnAntPathRequestMatcherType() { + public void pathPatternWhenHttpMethodAndPatternParamsThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry - .requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name())); + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(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(PathPatternRequestMatcher.withDefaults().matcher("/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 +124,7 @@ public void dispatcherTypeMatchersWhenHttpMethodAndPatternParamsThenReturnAntPat } @Test - public void dispatcherMatchersWhenPatternParamThenReturnAntPathRequestMatcherType() { + public void dispatcherMatchersWhenPatternParamThenReturnPathPatternRequestMatcherType() { List requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(DispatcherType.INCLUDE); assertThat(requestMatchers).isNotEmpty(); assertThat(requestMatchers).hasSize(1); @@ -144,252 +132,36 @@ public void dispatcherMatchersWhenPatternParamThenReturnAntPathRequestMatcherTyp } @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 7a4cb72b104..1adbaf66b97 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,7 @@ 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.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -150,8 +150,8 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(new AntPathRequestMatcher("/api/**")) - .requestMatchers(new AntPathRequestMatcher("/oauth/**"))) + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/api/**")) + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/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 6aa7666b5da..bf86f97e1a9 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.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; @@ -195,13 +195,13 @@ public void configureWhenHttpBasicAndRequestUnauthorizedThenReturnWWWAuthenticat } @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 +226,21 @@ public void configureWhenRequestMatcherProvidedThenRequestMatcherUsed() { } @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(PathPatternRequestMatcher.withDefaults().matcher("/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(PathPatternRequestMatcher.withDefaults().matcher("/public/**")); assertThat(securityFilterChain.getFilters()).isEmpty(); } @@ -482,7 +482,7 @@ static class RequestMatcherAntConfig { SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatcher(new AntPathRequestMatcher("/api/**")); + .securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/api/**")); return http.build(); // @formatter:on } @@ -534,8 +534,9 @@ static class SecurityNoneConfig { @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 450a3dfdc17..62845140c62 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.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 @@ void validateWhenFilterSecurityInterceptorConfiguredThenValidates() { @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 @@ void validateWhenAnyRequestMatcherIsPresentThenUnreachableFilterChainException() @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 @@ void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainExceptio @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 2b58af889fb..fb3389e86cf 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 @@ -37,17 +37,17 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; 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.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 +130,13 @@ static class DefaultConfig { static class MvcMatcherConfig { @Bean - WebSecurityCustomizer webSecurityCustomizer(HandlerMappingIntrospector introspector) { - return (web) -> web.ignoring().requestMatchers(new MvcRequestMatcher(introspector, "/path")); + PathPatternRequestMatcherBuilderFactoryBean pathPatternRequestMatcherBuilder() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + WebSecurityCustomizer webSecurityCustomizer(PathPatternRequestMatcher.Builder builder) { + return (web) -> web.ignoring().requestMatchers(builder.matcher("/path")); } @Bean @@ -168,9 +173,15 @@ String path() { 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"); + PathPatternRequestMatcherBuilderFactoryBean pathPatternRequestMatcherBuilder() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 90297c75ef6..866cd95503c 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.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()); @@ -89,16 +76,9 @@ HttpServletRequestTransformer httpServletRequestTransformer() { } - @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 865b99ee21e..00000000000 --- 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 311bae361d1..450e3b2396b 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 @@ -63,7 +63,6 @@ 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; @@ -106,14 +105,13 @@ public void loadConfigWhenSecurityFilterChainsHaveOrderThenFilterChainsOrdered() 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 void loadConfigWhenSecurityFilterChainsHaveOrderOnBeanDefinitionsThenFilt 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 void loadConfigWhenOnlyWebSecurityCustomizerThenDefaultFilterChainCreated 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 void loadConfigWhenWebSecurityCustomizerAndFilterChainThenFilterChainsOrd 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 void loadConfigWhenCustomizersHaveOrderThenCustomizersOrdered() { 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 @@ static class SortedSecurityFilterChainConfig { SecurityFilterChain filterChain1(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role1/**")) + .securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role1/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("1") ) @@ -433,7 +427,7 @@ SecurityFilterChain filterChain1(HttpSecurity http) throws Exception { SecurityFilterChain filterChain2(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role2/**")) + .securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role2/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("2") ) @@ -446,7 +440,7 @@ SecurityFilterChain filterChain2(HttpSecurity http) throws Exception { SecurityFilterChain filterChain3(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role3/**")) + .securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role3/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("3") ) @@ -477,7 +471,7 @@ static class OrderOnBeanDefinitionsSecurityFilterChainConfig { SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role1/**")) + .securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role1/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("1") ) @@ -734,7 +728,7 @@ public WebSecurityCustomizer webSecurityCustomizer() { SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off return http - .securityMatcher(new AntPathRequestMatcher("/role1/**")) + .securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role1/**")) .authorizeRequests((authorize) -> authorize .anyRequest().hasRole("1") ) @@ -773,7 +767,7 @@ static class TwoSecurityFilterChainConfig { public SecurityFilterChain path1(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**"))) + .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/path1/**"))) .authorizeRequests((requests) -> requests.anyRequest().authenticated()); // @formatter:on return http.build(); @@ -797,7 +791,7 @@ static class TwoSecurityFilterChainDebugConfig { public SecurityFilterChain path1(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**"))) + .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/path1/**"))) .authorizeRequests((requests) -> requests.anyRequest().authenticated()); // @formatter:on return http.build(); @@ -822,7 +816,7 @@ static class MultipleSecurityFilterChainConfig { public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user"))) + .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/user"))) .authorizeRequests((requests) -> requests.anyRequest().hasRole("USER")); // @formatter:on return http.build(); @@ -833,7 +827,7 @@ public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception { public SecurityFilterChain path1(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin"))) + .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/admin"))) .authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN")); // @formatter:on return http.build(); @@ -864,7 +858,7 @@ public WebSecurityCustomizer webSecurityCustomizer() { public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user"))) + .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/user"))) .authorizeRequests((requests) -> requests.anyRequest().hasRole("USER")); // @formatter:on return http.build(); @@ -875,7 +869,7 @@ public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception { public SecurityFilterChain admin(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin"))) + .securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/admin"))) .authorizeRequests((requests) -> requests.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 e34de7c8835..d04ca122510 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,7 +22,7 @@ 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; @@ -55,19 +55,20 @@ public void testRequestMatcherIsTypeRegexMatcher() { } @Test - public void testGetRequestMatcherIsTypeAntPathRequestMatcher() { + public void testGetRequestMatcherIsTypePathPatternRequestMatcher() { List requestMatchers = this.registry - .requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name())); + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(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(PathPatternRequestMatcher.withDefaults().matcher("/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 b2bd973beef..20507ab65f9 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 @@ -68,7 +68,6 @@ 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 +80,6 @@ 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 +146,7 @@ public void configureNoParameterWhenAnyRequestIncompleteMappingThenException() { 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 +687,7 @@ public void getWhenDeniedThenParameterizedAuthorizationDeniedEventIsPublished() @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 +1061,16 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { static class ServletPathConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 +1359,7 @@ SecurityObservationSettings observabilityDefaults() { @Configuration @EnableWebSecurity @EnableWebMvc - static class MvcRequestMatcherBuilderConfig { + static class PathPatternRequestMatcherBuilderConfig { @Bean SecurityFilterChain security(HttpSecurity http) throws Exception { 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 992dc0de1f6..e2f2fb5c73f 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 @@ -33,6 +33,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextImpl; @@ -42,13 +43,12 @@ 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; @@ -77,7 +77,6 @@ public class AuthorizeRequestsTests { public void setup() { this.servletContext = spy(MockServletContext.mvc()); this.request = new MockHttpServletRequest(this.servletContext, "GET", ""); - this.request.setMethod("GET"); this.response = new MockHttpServletResponse(); this.chain = new MockFilterChain(); } @@ -110,11 +109,11 @@ public void postWhenPostDenyAllInLambdaThenRespondsWithForbidden() throws Except @Test public void antMatchersPathVariables() throws Exception { loadConfig(AntPatchersPathVariables.class); - 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.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); } @@ -123,11 +122,11 @@ public void antMatchersPathVariables() throws Exception { @Test public void antMatchersPathVariablesCaseInsensitive() throws Exception { loadConfig(AntPatchersPathVariables.class); - 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.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); } @@ -136,11 +135,11 @@ public void antMatchersPathVariablesCaseInsensitive() throws Exception { @Test public void antMatchersPathVariablesCaseInsensitiveCamelCaseVariables() throws Exception { loadConfig(AntMatchersPathVariablesCamelCaseVariables.class); - 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.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); } @@ -199,7 +198,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests((requests) -> requests - .requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll()); + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/**")).denyAll()); // @formatter:on return http.build(); } @@ -220,7 +219,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests((authorize) -> authorize - .requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll() + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/**")).denyAll() ); // @formatter:on return http.build(); @@ -239,10 +238,13 @@ static class AntPatchersPathVariables { @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(); @@ -261,10 +263,13 @@ static class AntMatchersPathVariablesCamelCaseVariables { @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(); @@ -378,14 +383,18 @@ String path() { static class MvcMatcherServletPathConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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(); } @@ -413,14 +422,18 @@ String path() { static class MvcMatcherServletPathInLambdaConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 377445bb0a4..20bb13e739f 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,7 +28,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.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.bind.annotation.RequestMapping; @@ -109,7 +109,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .csrf((csrf) -> csrf - .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path")) + .requireCsrfProtectionMatcher(PathPatternRequestMatcher.withDefaults().matcher("/path")) .ignoringRequestMatchers(this.requestMatcher)); return http.build(); // @formatter:on @@ -129,7 +129,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .csrf((csrf) -> csrf - .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path")) + .requireCsrfProtectionMatcher(PathPatternRequestMatcher.withDefaults().matcher("/path")) .ignoringRequestMatchers(this.requestMatcher) ); return http.build(); @@ -149,7 +149,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .csrf((csrf) -> csrf - .ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf")) + .ignoringRequestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/no-csrf")) .ignoringRequestMatchers(this.requestMatcher)); return http.build(); // @formatter:on @@ -169,7 +169,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .csrf((csrf) -> csrf - .ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf")) + .ignoringRequestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/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 ce081911994..4220b752ace 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,7 @@ 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.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -906,7 +906,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .formLogin(withDefaults()) .logout((logout) -> logout - .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))); + .logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/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 46d0fbe54a8..93af0fe7255 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 void filterChainProxyBuilderIgnoringResources() { 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 ad1de31fe23..e20a47c00aa 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,7 +32,7 @@ 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.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; @@ -92,7 +92,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .exceptionHandling((handling) -> handling .defaultAccessDeniedHandlerFor( this.teapotDeniedHandler, - new AntPathRequestMatcher("/hello/**")) + PathPatternRequestMatcher.withDefaults().matcher("/hello/**")) .defaultAccessDeniedHandlerFor( new AccessDeniedHandlerImpl(), AnyRequestMatcher.INSTANCE)); @@ -119,7 +119,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .exceptionHandling((exceptionHandling) -> exceptionHandling .defaultAccessDeniedHandlerFor( this.teapotDeniedHandler, - new AntPathRequestMatcher("/hello/**") + PathPatternRequestMatcher.withDefaults().matcher("/hello/**") ) .defaultAccessDeniedHandlerFor( new AccessDeniedHandlerImpl(), @@ -148,7 +148,7 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .exceptionHandling((handling) -> handling .defaultAccessDeniedHandlerFor( this.teapotDeniedHandler, - new AntPathRequestMatcher("/hello/**"))); + PathPatternRequestMatcher.withDefaults().matcher("/hello/**"))); return http.build(); // @formatter:on } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java index b82c2a57a32..98340ec2716 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java @@ -39,6 +39,7 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * @author Rob Winch @@ -48,8 +49,6 @@ public class HttpSecurityLogoutTests { AnnotationConfigWebApplicationContext context; - MockHttpServletRequest request; - MockHttpServletResponse response; MockFilterChain chain; @@ -59,7 +58,6 @@ public class HttpSecurityLogoutTests { @BeforeEach public void setup() { - this.request = new MockHttpServletRequest("GET", ""); this.response = new MockHttpServletResponse(); this.chain = new MockFilterChain(); } @@ -77,11 +75,10 @@ public void clearAuthenticationFalse() throws Exception { loadConfig(ClearAuthenticationFalseConfig.class); SecurityContext currentContext = SecurityContextHolder.createEmptyContext(); currentContext.setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); - this.request.getSession() + MockHttpServletRequest request = post("/logout").build(); + request.getSession() .setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, currentContext); - this.request.setMethod("POST"); - this.request.setServletPath("/logout"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(currentContext.getAuthentication()).isNotNull(); } 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 85d78389884..76bc331be1f 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 @@ -32,19 +32,20 @@ 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.config.web.PathPatternRequestMatcherBuilderFactoryBean; 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; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * @author Rob Winch @@ -54,8 +55,6 @@ public class HttpSecurityRequestMatchersTests { AnnotationConfigWebApplicationContext context; - MockHttpServletRequest request; - MockHttpServletResponse response; MockFilterChain chain; @@ -65,8 +64,6 @@ public class HttpSecurityRequestMatchersTests { @BeforeEach public void setup() { - this.request = new MockHttpServletRequest("GET", ""); - this.request.setMethod("GET"); this.response = new MockHttpServletResponse(); this.chain = new MockFilterChain(); } @@ -87,70 +84,64 @@ public void mvcMatcherGetFiltersNoUnsupportedMethodExceptionFromDummyRequest() { @Test public void requestMatchersMvcMatcherServletPath() throws Exception { loadConfig(RequestMatchersMvcMatcherServeltPathConfig.class); - this.request.setServletPath("/spring"); - this.request.setRequestURI("/spring/path"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + MockHttpServletRequest request = get().requestUri(null, "/spring", "/path").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); - this.request.setServletPath(""); - this.request.setRequestURI("/path"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get().requestUri(null, "", "/path").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); setup(); - this.request.setServletPath("/other"); - this.request.setRequestURI("/other/path"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get().requestUri(null, "/other", "/path").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); } @Test public void requestMatcherWhensMvcMatcherServletPathInLambdaThenPathIsSecured() throws Exception { loadConfig(RequestMatchersMvcMatcherServletPathInLambdaConfig.class); - this.request.setServletPath("/spring"); - this.request.setRequestURI("/spring/path"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + MockHttpServletRequest request = get().requestUri(null, "/spring", "/path").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); - this.request.setServletPath(""); - this.request.setRequestURI("/path"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get().requestUri(null, "", "/path").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); setup(); - this.request.setServletPath("/other"); - this.request.setRequestURI("/other/path"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get().requestUri(null, "/other", "/path").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); } @Test public void requestMatcherWhenMultiMvcMatcherInLambdaThenAllPathsAreDenied() throws Exception { loadConfig(MultiMvcMatcherInLambdaConfig.class); - this.request.setRequestURI("/test-1"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + MockHttpServletRequest request = get("/test-1").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); - this.request.setRequestURI("/test-2"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get("/test-2").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); - this.request.setRequestURI("/test-3"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get("/test-3").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @Test public void requestMatcherWhenMultiMvcMatcherThenAllPathsAreDenied() throws Exception { loadConfig(MultiMvcMatcherConfig.class); - this.request.setRequestURI("/test-1"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + MockHttpServletRequest request = get("/test-1").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); - this.request.setRequestURI("/test-2"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get("/test-2").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); - this.request.setRequestURI("/test-3"); - this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + request = get("/test-3").build(); + this.springSecurityFilterChain.doFilter(request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @@ -167,16 +158,20 @@ public void loadConfig(Class... configs) { @EnableWebMvc static class MultiMvcMatcherInLambdaConfig { + @Bean + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + @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()); @@ -185,12 +180,11 @@ SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspe } @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() @@ -216,16 +210,20 @@ String path() { @EnableWebMvc static class MultiMvcMatcherConfig { + @Bean + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + @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()); @@ -234,12 +232,11 @@ SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspe } @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 @@ -264,10 +261,15 @@ String path() { static class MvcMatcherConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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()); @@ -298,11 +300,16 @@ String path() { static class RequestMatchersMvcMatcherConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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()); @@ -333,11 +340,16 @@ String path() { static class RequestMatchersMvcMatcherInLambdaConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 @@ -365,13 +377,16 @@ String path() { static class RequestMatchersMvcMatcherServeltPathConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); - mvcMatcherBuilder.servletPath("/spring"); + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 @@ -403,13 +418,16 @@ String path() { static class RequestMatchersMvcMatcherServletPathInLambdaConfig { @Bean - SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); - mvcMatcherBuilder.servletPath("/spring"); + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 c6afdf35720..34b3d3a3790 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.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; @@ -67,7 +67,7 @@ public class HttpSecuritySecurityMatchersNoMvcTests { @BeforeEach public void setup() throws Exception { - this.request = new MockHttpServletRequest("GET", ""); + this.request = new MockHttpServletRequest(); this.request.setMethod("GET"); this.response = new MockHttpServletResponse(); this.chain = new MockFilterChain(); @@ -83,15 +83,15 @@ public void cleanup() { @Test public void securityMatcherWhenNoMvcThenAntMatcher() throws Exception { loadConfig(SecurityMatcherNoMvcConfig.class); - this.request.setServletPath("/path"); + this.request.setRequestURI("/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); - this.request.setServletPath("/path.html"); + this.request.setRequestURI("/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); setup(); - this.request.setServletPath("/path/"); + this.request.setRequestURI("/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); List requestMatchers = this.springSecurityFilterChain.getFilterChains() .stream() @@ -101,7 +101,7 @@ public void securityMatcherWhenNoMvcThenAntMatcher() throws Exception { .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 9de85b6957d..ad624affdbf 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 @@ -32,6 +32,7 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -39,12 +40,11 @@ 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 +356,18 @@ String path() { static class SecurityMatchersMvcMatcherServletPathConfig { @Bean - SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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 +395,18 @@ String path() { static class SecurityMatchersMvcMatcherServletPathInLambdaConfig { @Bean - SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector) - .servletPath("/spring"); + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + + @Bean + 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/NamespaceRememberMeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java index 0d02e44132a..0831bdc7ce8 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.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 @@ static class WithoutKeyConfig extends UsersConfig { 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/RequestMatcherConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java index d28dca2d42a..1aa2919a17d 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,7 +27,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.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -79,9 +79,9 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .securityMatchers((security) -> security - .requestMatchers(new AntPathRequestMatcher("/api/**"))) + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/api/**"))) .securityMatchers((security) -> security - .requestMatchers(new AntPathRequestMatcher("/oauth/**"))) + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/oauth/**"))) .authorizeRequests((requests) -> requests .anyRequest().denyAll()); return http.build(); @@ -99,10 +99,10 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http .securityMatchers((secure) -> secure - .requestMatchers(new AntPathRequestMatcher("/api/**")) + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/api/**")) ) .securityMatchers((securityMatchers) -> securityMatchers - .requestMatchers(new AntPathRequestMatcher("/oauth/**")) + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/oauth/**")) ) .authorizeRequests((authorize) -> authorize .anyRequest().denyAll() diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java index cd32887961c..98998e31e85 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java @@ -30,14 +30,10 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextImpl; 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.context.HttpRequestResponseHolder; -import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.security.web.csrf.CsrfToken; import org.springframework.security.web.csrf.CsrfTokenRequestHandler; import org.springframework.security.web.csrf.DeferredCsrfToken; @@ -46,14 +42,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.config.Customizer.withDefaults; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * @author Rob Winch */ public class SessionManagementConfigurerServlet31Tests { - MockHttpServletRequest request; - MockHttpServletResponse response; MockFilterChain chain; @@ -64,7 +59,6 @@ public class SessionManagementConfigurerServlet31Tests { @BeforeEach public void setup() { - this.request = new MockHttpServletRequest("GET", ""); this.response = new MockHttpServletResponse(); this.chain = new MockFilterChain(); } @@ -78,13 +72,9 @@ public void teardown() { @Test public void changeSessionIdThenPreserveParameters() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); + MockHttpServletRequest request = post("/login").param("username", "user").param("password", "password").build(); String id = request.getSession().getId(); request.getSession(); - request.setServletPath("/login"); - request.setMethod("POST"); - request.setParameter("username", "user"); - request.setParameter("password", "password"); HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); CsrfTokenRequestHandler handler = new XorCsrfTokenRequestAttributeHandler(); DeferredCsrfToken deferredCsrfToken = repository.loadDeferredToken(request, this.response); @@ -106,15 +96,6 @@ private void loadConfig(Class... classes) { this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", Filter.class); } - private void login(Authentication auth) { - HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository(); - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(this.request, this.response); - repo.loadContext(requestResponseHolder); - SecurityContextImpl securityContextImpl = new SecurityContextImpl(); - securityContextImpl.setAuthentication(auth); - repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse()); - } - @Configuration @EnableWebSecurity static class SessionManagementDefaultSessionFixationServlet31Config { 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 d0728428dc7..b0359a68b22 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 @@ -33,6 +33,7 @@ import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean; import org.springframework.security.core.userdetails.PasswordEncodedUser; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; @@ -41,12 +42,11 @@ 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; @@ -131,14 +131,19 @@ public void loadConfig(Class... configs) { @EnableWebMvc static class MvcMatcherConfig { + @Bean + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + @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(); } @@ -165,16 +170,20 @@ String path() { @EnableWebMvc static class MvcMatcherServletPathConfig { + @Bean + PathPatternRequestMatcherBuilderFactoryBean pathPattern() { + return new PathPatternRequestMatcherBuilderFactoryBean(); + } + @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/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java index cc1a30a381f..d24fc4f723c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java @@ -107,6 +107,7 @@ import org.springframework.security.web.context.HttpRequestResponseHolder; import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.security.web.session.HttpSessionDestroyedEvent; import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher; import org.springframework.test.util.ReflectionTestUtils; @@ -127,6 +128,7 @@ import static org.springframework.security.config.annotation.SecurityContextChangedListenerArgumentMatchers.setAuthentication; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; @@ -185,8 +187,7 @@ public class OAuth2LoginConfigurerTests { @BeforeEach public void setup() { - this.request = new MockHttpServletRequest("GET", ""); - this.request.setServletPath("/login/oauth2/code/google"); + this.request = TestMockHttpServletRequests.get("/login/oauth2/code/google").build(); this.response = new MockHttpServletResponse(); this.filterChain = new MockFilterChain(); } @@ -347,7 +348,7 @@ public void oauth2LoginConfigLoginProcessingUrl() throws Exception { loadConfig(OAuth2LoginConfigLoginProcessingUrl.class); // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); - this.request.setServletPath("/login/oauth2/google"); + this.request.setRequestURI("/login/oauth2/google"); this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -381,8 +382,7 @@ public void oauth2LoginWithCustomAuthorizationRequestParameters() throws Excepti // @formatter:on given(resolver.resolve(any())).willReturn(result); String requestUri = "/oauth2/authorization/google"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = TestMockHttpServletRequests.get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).isEqualTo( "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1"); @@ -394,8 +394,7 @@ public void oauth2LoginWithCustomAuthorizationRequestParametersAndResolverAsBean // @formatter:off // @formatter:on String requestUri = "/oauth2/authorization/google"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = TestMockHttpServletRequests.get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).isEqualTo( "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1"); @@ -418,8 +417,7 @@ public void requestWhenOauth2LoginWithCustomAuthorizationRequestParametersThenPa // @formatter:on given(resolver.resolve(any())).willReturn(result); String requestUri = "/oauth2/authorization/google"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = TestMockHttpServletRequests.get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).isEqualTo( "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1"); @@ -432,8 +430,7 @@ public void oauth2LoginWithAuthorizationRedirectStrategyThenCustomAuthorizationR RedirectStrategy redirectStrategy = this.context .getBean(OAuth2LoginConfigCustomAuthorizationRedirectStrategy.class).redirectStrategy; String requestUri = "/oauth2/authorization/google"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); then(redirectStrategy).should().sendRedirect(any(), any(), anyString()); } @@ -445,8 +442,7 @@ public void requestWhenOauth2LoginWithCustomAuthorizationRedirectStrategyThenCus RedirectStrategy redirectStrategy = this.context .getBean(OAuth2LoginConfigCustomAuthorizationRedirectStrategyInLambda.class).redirectStrategy; String requestUri = "/oauth2/authorization/google"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); then(redirectStrategy).should().sendRedirect(any(), any(), anyString()); } @@ -456,8 +452,7 @@ public void requestWhenOauth2LoginWithCustomAuthorizationRedirectStrategyThenCus public void oauth2LoginWithOneClientConfiguredThenRedirectForAuthorization() throws Exception { loadConfig(OAuth2LoginConfig.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).matches("http://localhost/oauth2/authorization/google"); } @@ -467,8 +462,7 @@ public void oauth2LoginWithOneClientConfiguredThenRedirectForAuthorization() thr public void oauth2LoginWithOneClientConfiguredAndFormLoginThenRedirectDefaultLoginPage() throws Exception { loadConfig(OAuth2LoginConfigFormLogin.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).matches("http://localhost/login"); } @@ -479,8 +473,7 @@ public void oauth2LoginWithOneClientConfiguredAndRequestFaviconNotAuthenticatedT throws Exception { loadConfig(OAuth2LoginConfig.class); String requestUri = "/favicon.ico"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.request.addHeader(HttpHeaders.ACCEPT, new MediaType("image", "*").toString()); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).matches("http://localhost/login"); @@ -491,8 +484,7 @@ public void oauth2LoginWithOneClientConfiguredAndRequestFaviconNotAuthenticatedT public void oauth2LoginWithMultipleClientsConfiguredThenRedirectDefaultLoginPage() throws Exception { loadConfig(OAuth2LoginConfigMultipleClients.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).matches("http://localhost/login"); } @@ -503,8 +495,7 @@ public void oauth2LoginWithOneClientConfiguredAndRequestXHRNotAuthenticatedThenD throws Exception { loadConfig(OAuth2LoginConfig.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.request.addHeader("X-Requested-With", "XMLHttpRequest"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).doesNotMatch("http://localhost/oauth2/authorization/google"); @@ -515,8 +506,7 @@ public void oauth2LoginWithHttpBasicOneClientConfiguredAndRequestXHRNotAuthentic throws Exception { loadConfig(OAuth2LoginWithHttpBasicConfig.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.request.addHeader("X-Requested-With", "XMLHttpRequest"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getStatus()).isEqualTo(401); @@ -527,8 +517,7 @@ public void oauth2LoginWithXHREntryPointOneClientConfiguredAndRequestXHRNotAuthe throws Exception { loadConfig(OAuth2LoginWithXHREntryPointConfig.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.request.addHeader("X-Requested-With", "XMLHttpRequest"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getStatus()).isEqualTo(401); @@ -540,8 +529,7 @@ public void oauth2LoginWithOneAuthorizationCodeClientAndOtherClientsConfiguredTh throws Exception { loadConfig(OAuth2LoginConfigAuthorizationCodeClientAndOtherClients.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).matches("http://localhost/oauth2/authorization/google"); } @@ -550,8 +538,7 @@ public void oauth2LoginWithOneAuthorizationCodeClientAndOtherClientsConfiguredTh public void oauth2LoginWithCustomLoginPageThenRedirectCustomLoginPage() throws Exception { loadConfig(OAuth2LoginConfigCustomLoginPage.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).matches("http://localhost/custom-login"); } @@ -560,8 +547,7 @@ public void oauth2LoginWithCustomLoginPageThenRedirectCustomLoginPage() throws E public void requestWhenOauth2LoginWithCustomLoginPageInLambdaThenRedirectCustomLoginPage() throws Exception { loadConfig(OAuth2LoginConfigCustomLoginPageInLambda.class); String requestUri = "/"; - this.request = new MockHttpServletRequest("GET", requestUri); - this.request.setServletPath(requestUri); + this.request = get(requestUri).build(); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getRedirectedUrl()).matches("http://localhost/custom-login"); } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerConfigurationTests.java index df28e06209a..30907b5e8d3 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerConfigurationTests.java @@ -89,6 +89,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link OidcUserRefreshedEventListener} with {@link OAuth2LoginConfigurer}. @@ -147,8 +148,7 @@ public class OidcUserRefreshedEventListenerConfigurationTests { @BeforeEach public void setUp() { - this.request = new MockHttpServletRequest("GET", ""); - this.request.setServletPath("/"); + this.request = get("/").build(); this.response = new MockHttpServletResponse(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(this.request, this.response)); } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerTests.java index 6b8f82a8bd0..84c7a3e42b9 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OidcUserRefreshedEventListenerTests.java @@ -42,6 +42,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link OidcUserRefreshedEventListener}. @@ -64,8 +65,7 @@ public void setUp() { this.eventListener = new OidcUserRefreshedEventListener(); this.eventListener.setSecurityContextRepository(this.securityContextRepository); - this.request = new MockHttpServletRequest("GET", ""); - this.request.setServletPath("/"); + this.request = get("/").build(); this.response = new MockHttpServletResponse(); } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java index f43ae69d86c..102bf1e5170 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java @@ -94,6 +94,7 @@ import org.springframework.security.web.context.HttpRequestResponseHolder; import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -190,8 +191,7 @@ static void createResponse() throws Exception { @BeforeEach public void setup() { - this.request = new MockHttpServletRequest("POST", ""); - this.request.setServletPath("/login/saml2/sso/test-rp"); + this.request = TestMockHttpServletRequests.post("/login/saml2/sso/test-rp").build(); this.response = new MockHttpServletResponse(); this.filterChain = new MockFilterChain(); } @@ -430,7 +430,6 @@ public void saml2LoginWhenCustomAuthenticationProviderThenUses() throws Exceptio private void performSaml2Login(String expected) throws IOException, ServletException { // setup authentication parameters this.request.setRequestURI("/login/saml2/sso/registration-id"); - this.request.setServletPath("/login/saml2/sso/registration-id"); this.request.setParameter("SAMLResponse", Base64.getEncoder().encodeToString("saml2-xml-response-object".getBytes())); // perform test diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurerTests.java index 36c2d0895cb..573e5331a09 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurerTests.java @@ -38,6 +38,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; @@ -76,7 +77,8 @@ import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.RequestPostProcessor; @@ -158,8 +160,7 @@ public void setup() { Collections.emptyMap()); principal.setRelyingPartyRegistrationId("registration-id"); this.user = new Saml2Authentication(principal, "response", AuthorityUtils.createAuthorityList("ROLE_USER")); - this.request = new MockHttpServletRequest("POST", ""); - this.request.setServletPath("/login/saml2/sso/test-rp"); + this.request = TestMockHttpServletRequests.post("/login/saml2/sso/test-rp").build(); this.response = new MockHttpServletResponse(); } @@ -620,7 +621,7 @@ SecurityFilterChain web(HttpSecurity http) throws Exception { .saml2Logout((saml2) -> saml2.addObjectPostProcessor(new ObjectPostProcessor() { @Override public O postProcess(O filter) { - filter.setLogoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")); + filter.setLogoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/logout")); return filter; } })); 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 906deec0e98..57f9a82750f 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 @@ void compositeFilterChainProxyHasHints() { .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 d75ce815d58..48568cbf04e 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.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 void validateCustomMetadataSource() { @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 21972bac10a..5bd2d50f7a9 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 void expressionsAreSupported() { 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 void interceptUrlsSupportPropertyPlaceholders() { @Test public void parsingWithinFilterSecurityInterceptorIsSuccessful() { // @formatter:off - setContext("" + - "" + setContext("" + "" + " " + " " @@ -132,9 +129,7 @@ public void parsingInterceptUrlServletPathFails() { } private FilterInvocation createFilterInvocation(String path, String method) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - request.setRequestURI(path); - request.setMethod(method); + MockHttpServletRequest request = new MockHttpServletRequest(method, path); return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain()); } 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 9088bb443f9..0665978b434 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 f0f983022f2..69245d6bac1 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.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.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 void requestWhenUsingPathVariablesAndTypeConversionAndAuthorizationManage 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 void requestWhenUsingMvcMatchersAndPathVariablesAndAuthorizationManagerTh 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 void configureWhenUsingDefaultMatcherAndServletPathThenNoException() { .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/Saml2LogoutBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/Saml2LogoutBeanDefinitionParserTests.java index 4045c1b689e..71da35955bd 100644 --- a/config/src/test/java/org/springframework/security/config/http/Saml2LogoutBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/Saml2LogoutBeanDefinitionParserTests.java @@ -134,8 +134,7 @@ public void setup() { principal.setRelyingPartyRegistrationId("registration-id"); this.saml2User = new Saml2Authentication(principal, "response", AuthorityUtils.createAuthorityList("ROLE_USER")); - this.request = new MockHttpServletRequest("POST", ""); - this.request.setServletPath("/login/saml2/sso/test-rp"); + this.request = new MockHttpServletRequest("POST", "/login/saml2/sso/test-rp"); this.response = new MockHttpServletResponse(); } diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java index 03c50c9db91..333c2db61fe 100644 --- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java +++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java @@ -26,10 +26,7 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.config.util.InMemoryXmlApplicationContext; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextImpl; -import org.springframework.security.web.context.HttpRequestResponseHolder; -import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; @@ -61,7 +58,7 @@ public class SessionManagementConfigServlet31Tests { @BeforeEach public void setup() { - this.request = new MockHttpServletRequest("GET", ""); + this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); this.chain = new MockFilterChain(); } @@ -75,12 +72,11 @@ public void teardown() { @Test public void changeSessionIdThenPreserveParameters() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); + MockHttpServletRequest request = TestMockHttpServletRequests.post("/login") + .param("username", "user") + .param("password", "password") + .build(); request.getSession(); - request.setServletPath("/login"); - request.setMethod("POST"); - request.setParameter("username", "user"); - request.setParameter("password", "password"); request.getSession().setAttribute("attribute1", "value1"); String id = request.getSession().getId(); // @formatter:off @@ -99,12 +95,11 @@ public void changeSessionIdThenPreserveParameters() throws Exception { @Test public void changeSessionId() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); + MockHttpServletRequest request = TestMockHttpServletRequests.post("/login") + .param("username", "user") + .param("password", "password") + .build(); request.getSession(); - request.setServletPath("/login"); - request.setMethod("POST"); - request.setParameter("username", "user"); - request.setParameter("password", "password"); String id = request.getSession().getId(); // @formatter:off loadContext("\n" @@ -124,13 +119,4 @@ private void loadContext(String context) { this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", Filter.class); } - private void login(Authentication auth) { - HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository(); - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(this.request, this.response); - repo.loadContext(requestResponseHolder); - SecurityContextImpl securityContextImpl = new SecurityContextImpl(); - securityContextImpl.setAuthentication(auth); - repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse()); - } - } 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 1c2ca465faf..0cd8908c15a 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,7 @@ 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 org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; /** * @author Rob Winch @@ -44,7 +44,7 @@ public void init(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests((requests) -> requests - .requestMatchers(new AntPathRequestMatcher(this.permitAllPattern)).permitAll() + .requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(this.permitAllPattern)).permitAll() .anyRequest().authenticated()); // @formatter:on if (http.getConfigurer(FormLoginConfigurer.class) == null) { diff --git a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java index c47bf68b6e7..01d2f83c617 100644 --- a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java @@ -60,7 +60,7 @@ public class CustomHttpSecurityConfigurerTests { @BeforeEach public void setup() { - this.request = new MockHttpServletRequest("GET", ""); + this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); this.chain = new MockFilterChain(); this.request.setMethod("GET"); @@ -76,7 +76,7 @@ public void cleanup() { @Test public void customConfiguerPermitAll() throws Exception { loadContext(Config.class); - this.request.setPathInfo("/public/something"); + this.request.setRequestURI("/public/something"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); } @@ -84,7 +84,7 @@ public void customConfiguerPermitAll() throws Exception { @Test public void customConfiguerFormLogin() throws Exception { loadContext(Config.class); - this.request.setPathInfo("/requires-authentication"); + this.request.setRequestURI("/requires-authentication"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getRedirectedUrl()).endsWith("/custom"); } @@ -92,7 +92,7 @@ public void customConfiguerFormLogin() throws Exception { @Test public void customConfiguerCustomizeDisablesCsrf() throws Exception { loadContext(ConfigCustomize.class); - this.request.setPathInfo("/public/something"); + this.request.setRequestURI("/public/something"); this.request.setMethod("POST"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); @@ -101,7 +101,7 @@ public void customConfiguerCustomizeDisablesCsrf() throws Exception { @Test public void customConfiguerCustomizeFormLogin() throws Exception { loadContext(ConfigCustomize.class); - this.request.setPathInfo("/requires-authentication"); + this.request.setRequestURI("/requires-authentication"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getRedirectedUrl()).endsWith("/other"); } diff --git a/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java index 68a6c22ab1c..29e3cbbda14 100644 --- a/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java @@ -40,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link RelyingPartyRegistrationsBeanDefinitionParser}. @@ -282,9 +283,7 @@ public void parseWhenRelayStateResolverThenUses() { Converter relayStateResolver = this.spring.getContext().getBean(Converter.class); OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = this.spring.getContext() .getBean(OpenSaml4AuthenticationRequestResolver.class); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI("/saml2/authenticate/one"); - request.setServletPath("/saml2/authenticate/one"); + MockHttpServletRequest request = get("/saml2/authenticate/one").build(); authenticationRequestResolver.resolve(request); verify(relayStateResolver).convert(request); } diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDslTests.kt index 42eda2bbfc9..ed70c249152 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeRequestsDslTests.kt @@ -44,8 +44,6 @@ 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.servlet.config.annotation.EnableWebMvc -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer /** * Tests for [AuthorizeRequestsDsl] @@ -405,17 +403,11 @@ class AuthorizeRequestsDslTests { this.spring.register(MvcMatcherServletPathConfig::class.java).autowire() this.mockMvc.perform(MockMvcRequestBuilders.get("/spring/path") - .with { request -> - request.servletPath = "/spring" - request - }) + .servletPath("/spring")) .andExpect(status().isForbidden) this.mockMvc.perform(MockMvcRequestBuilders.get("/other/path") - .with { request -> - request.servletPath = "/other" - request - }) + .servletPath("/other")) .andExpect(status().isOk) } @@ -514,28 +506,15 @@ class AuthorizeRequestsDslTests { this.spring.register(MvcMatcherServletPathConfig::class.java).autowire() this.mockMvc.perform(MockMvcRequestBuilders.get("/spring/path") - .with { request -> - request.apply { - servletPath = "/spring" - } - }) + .servletPath("/spring")) .andExpect(status().isForbidden) this.mockMvc.perform(MockMvcRequestBuilders.put("/spring/path") - .with { request -> - request.apply { - servletPath = "/spring" - csrf() - } - }) + .servletPath("/spring")) .andExpect(status().isForbidden) this.mockMvc.perform(MockMvcRequestBuilders.get("/other/path") - .with { request -> - request.apply { - servletPath = "/other" - } - }) + .servletPath("/other")) .andExpect(status().isOk) } } 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 ae6568263d8..d631bfa8a01 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 @@ -43,7 +43,7 @@ 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.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 +176,7 @@ class CsrfDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { csrf { - requireCsrfProtectionMatcher = AntPathRequestMatcher("/test1") + requireCsrfProtectionMatcher = PathPatternRequestMatcher.withDefaults().matcher("/test1") } } return http.build() @@ -247,8 +247,8 @@ class CsrfDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { csrf { - requireCsrfProtectionMatcher = AntPathRequestMatcher("/**") - ignoringRequestMatchers(AntPathRequestMatcher("/test2")) + requireCsrfProtectionMatcher = PathPatternRequestMatcher.withDefaults().matcher("/**") + ignoringRequestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/test2")) } } return http.build() @@ -279,7 +279,7 @@ class CsrfDslTests { open fun filterChain(http: HttpSecurity): SecurityFilterChain { http { csrf { - requireCsrfProtectionMatcher = AntPathRequestMatcher("/**") + requireCsrfProtectionMatcher = PathPatternRequestMatcher.withDefaults().matcher("/**") 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 ed3e409cfff..8d99a850df1 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 7697ca4d67d..3b1b71d7c1e 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.withDefaults().matcher("/custom/logout") } } return http.build() @@ -307,8 +307,8 @@ class LogoutDslTests { open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { logout { - logoutRequestMatcher = AntPathRequestMatcher("/logout/**") - defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(), AntPathRequestMatcher("/logout/custom")) + logoutRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/logout/**") + defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(), PathPatternRequestMatcher.withDefaults().matcher("/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 b73b41f50de..011547f74e1 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/RequiresChannelDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/RequiresChannelDslTests.kt index 28632c1d926..439e64b6638 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/RequiresChannelDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/RequiresChannelDslTests.kt @@ -83,18 +83,12 @@ class RequiresChannelDslTests { this.spring.register(MvcMatcherServletPathConfig::class.java).autowire() this.mockMvc.perform(MockMvcRequestBuilders.get("/spring/path") - .with { request -> - request.servletPath = "/spring" - request - }) + .servletPath("/spring")) .andExpect(status().isFound) .andExpect(redirectedUrl("https://localhost/spring/path")) this.mockMvc.perform(MockMvcRequestBuilders.get("/other/path") - .with { request -> - request.servletPath = "/other" - request - }) + .servletPath("/other")) .andExpect(MockMvcResultMatchers.status().isOk) } 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 3edda234110..9158dea6868 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.withDefaults().matcher("/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 38a8cbfc8ce..b2796585d24 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 @@ -43,7 +43,7 @@ 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 5f29d2e71ae..d75bb163072 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,7 @@ - + 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 b1fa269cf8e..917656f8611 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 63ba250e94a..c88cbc620f5 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 6bb85a6b92a..fb011f12f28 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,12 @@ - + + + + + + + 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 aefa2c96a45..01d7e07a440 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 75e70f4d734..9438a8df387 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,5 @@ - + 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 b0c837f42d0..a1f9e770e70 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,5 @@ - + 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 3149fb4876e..009e1ed78fe 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,5 @@ - + 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 9044cf02e17..a17b11b18eb 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,5 @@ - + 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 9cc9f57a584..f3c09d2a9dd 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 03cdff6a8a1..cba0afb23e8 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,5 @@ - + 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 9b8b31c49a1..1701630e388 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,5 @@ - + 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 862f7d99a83..fd6aba58d07 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,5 @@ - + 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 17e62ece6a9..c4d93378ebd 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,5 @@ - + 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 ffff9b3032e..a32c00f3509 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,5 @@ - + 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 31b3400262a..1363e891525 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,5 @@ - + 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 e15c53e7e80..5c66f73a0c7 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,5 @@ - + 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 a3886876c84..ffc443b1026 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,5 @@ - + 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 37262122d52..c9c175d33d0 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,5 @@ - + 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 8beeec94a13..20ece21448a 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,5 @@ - + 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 8168a807e91..328e79b84b9 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,5 @@ - + 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 b03b8d7ee9a..d54f58d917a 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 d8e1e7511ea..f86a8955226 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,5 @@ - + 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 dfecf7ebe84..63f472c1dac 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,5 @@ - + 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 47787c9c843..35973a47800 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,5 @@ - + 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 c05b23c20ac..36263b2f396 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,5 @@ - + 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 4d93a59162e..f5b082d198c 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,5 @@ - + 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 e1bc1587afa..8d8ff135539 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,5 @@ - + 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 b41948934f1..e5ef1ea59fe 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,5 @@ - + 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 ec034128a53..d7cef81eb3e 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,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-AuthenticationManagerResolver.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-AuthenticationManagerResolver.xml index 384ecdca840..aac8f08552a 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-AuthenticationManagerResolver.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-AuthenticationManagerResolver.xml @@ -32,5 +32,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-BasicAndResourceServer.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-BasicAndResourceServer.xml index 580b31673d5..ef05c2c5ca6 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-BasicAndResourceServer.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-BasicAndResourceServer.xml @@ -33,5 +33,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-FormAndResourceServer.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-FormAndResourceServer.xml index 8fbc7dd03a8..2f579858c0c 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-FormAndResourceServer.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-FormAndResourceServer.xml @@ -33,5 +33,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwkSetUri.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwkSetUri.xml index aac12989e91..ab8a700e20f 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwkSetUri.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwkSetUri.xml @@ -39,5 +39,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-Jwt.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-Jwt.xml index e32bb32125c..1d1b002d000 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-Jwt.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-Jwt.xml @@ -32,5 +32,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwtCustomSecurityContextHolderStrategy.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwtCustomSecurityContextHolderStrategy.xml index d0ac087211a..f22ca3e3ac2 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwtCustomSecurityContextHolderStrategy.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-JwtCustomSecurityContextHolderStrategy.xml @@ -38,5 +38,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-MultipleIssuers.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-MultipleIssuers.xml index cba1d26936d..6ea749cb8a6 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-MultipleIssuers.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-MultipleIssuers.xml @@ -39,5 +39,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueToken.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueToken.xml index 9458e0d6e13..c050ec9e023 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueToken.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueToken.xml @@ -30,5 +30,5 @@ - + diff --git a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueTokenAndAuthenticationConverter.xml b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueTokenAndAuthenticationConverter.xml index b25d16ee9ed..99736580efd 100644 --- a/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueTokenAndAuthenticationConverter.xml +++ b/config/src/test/resources/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests-OpaqueTokenAndAuthenticationConverter.xml @@ -34,5 +34,5 @@ - + 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 d801c8c663c..1d7ef086911 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,5 @@ - + 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 005331dc00c..06c505c6983 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,5 @@ - + 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 b9280474ca8..7fbee4ee21b 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,5 @@ - + 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 ebd0289e714..ca6ed2a1ba1 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,5 @@ - + 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 e1380cf22e2..b6b5052df26 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,5 @@ - + 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 167abb99893..f6dcf1256db 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,5 @@ - + 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 2fbf13881f3..1b14632ad1f 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,5 @@ - + 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 e9e1ea4e21a..efb6fb756f4 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,5 @@ 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 738a9f42f81..0d966cb0928 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,5 @@ 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 78b86e2a1e7..de888a134d3 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,5 @@ 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 2d717a44968..3c8da7de57e 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,5 @@ - + 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 51e79b3283f..ffb5209ae30 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,5 @@ 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 faeeddcedc8..97ee0e38af0 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,5 @@ 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 6042ea290e8..e7da2cdbb48 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,5 @@ 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 f66b683c466..fe722ca85ed 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,5 @@ 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 0677224c0e7..ab7e7789556 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,5 @@ 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 5dbfac6d8f0..819f889f94c 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,5 @@ - + 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 c3f2cb95744..27c01d99079 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,5 @@ 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 369a5e14178..3bba2b6c829 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,5 @@ 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 e6e11567ab7..d8045766bb4 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,5 @@ 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 520c9a142d2..c293e31a240 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,5 @@ 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 457f9807ee5..f6578985bfb 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,5 @@ 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 1b9bff3c773..168ec42a069 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,6 @@ - - + + 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 f659f8841a2..dc857e82279 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,5 @@ 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 45280f776ee..0b52466d23a 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,5 @@ 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 968c474575c..5a4d2fa8405 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,5 @@ 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 92ec3ae9c28..91ccdd7929b 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,5 @@ 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 8cd46c54a2a..302eaa5d828 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,5 @@ 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 604b4fea114..146472ad7a3 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,5 @@ 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 a84edef1dc2..5f38701a67f 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,5 @@ 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 9e4deb3fa14..cb7e12c2289 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,5 @@ 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 62a808bafa8..dbd35d0edee 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,5 @@ 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 394b28eef1f..30ecc568c7e 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,5 @@ 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/pathpatternrequestmatcherbuilder.xml similarity index 90% rename from config/src/test/resources/org/springframework/security/config/http/handlermappingintrospector.xml rename to config/src/test/resources/org/springframework/security/config/http/pathpatternrequestmatcherbuilder.xml index 2b730a24656..ac37d5e4cc9 100644 --- a/config/src/test/resources/org/springframework/security/config/http/handlermappingintrospector.xml +++ b/config/src/test/resources/org/springframework/security/config/http/pathpatternrequestmatcherbuilder.xml @@ -24,6 +24,6 @@ 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/util/filtertest-valid.xml b/config/src/test/resources/org/springframework/security/util/filtertest-valid.xml index d12165a7b45..e40f1e94266 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/docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc b/docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc index 555a1b4323f..03115944071 100644 --- a/docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc +++ b/docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc @@ -128,7 +128,7 @@ This is helpful when, for example, wanting to run HTTP locally and HTTPS in prod Defines the `RequestMatcher` strategy used in the `FilterChainProxy` and the beans created by the `intercept-url` to match incoming requests. Options are currently `mvc`, `ant`, `regex` and `ciRegex`, for Spring MVC, ant, regular-expression and case-insensitive regular-expression respectively. A separate instance is created for each <> element using its <>, <> and <> attributes. -Ant paths are matched using an `AntPathRequestMatcher`, regular expressions are matched using a `RegexRequestMatcher` and for Spring MVC path matching the `MvcRequestMatcher` is used. +By default, paths are matched using a `PathPatternRequestMatcher`; however, regular expressions are matched using a `RegexRequestMatcher`. See the Javadoc for these classes for more details on exactly how the matching is performed. MVC is the default strategy if Spring MVC is present in the classpath, if not, Ant paths are used. @@ -226,7 +226,8 @@ Defines a reference to a Spring bean of type `AccessDeniedHandler`. [[nsa-cors]] == This element allows for configuring a `CorsFilter`. -If no `CorsFilter` or `CorsConfigurationSource` is specified and Spring MVC is on the classpath, a `HandlerMappingIntrospector` is used as the `CorsConfigurationSource`. +Either a `CorsFilter` or a `CorsConfigurationSource` must be specified. +If Spring MVC is present, then it will attempt to look up its `CorsConfigurationSource`. [[nsa-cors-attributes]] === Attributes diff --git a/docs/modules/ROOT/pages/servlet/authorization/authorize-http-requests.adoc b/docs/modules/ROOT/pages/servlet/authorization/authorize-http-requests.adoc index 2d435ff36ca..1ab2ba15058 100644 --- a/docs/modules/ROOT/pages/servlet/authorization/authorize-http-requests.adoc +++ b/docs/modules/ROOT/pages/servlet/authorization/authorize-http-requests.adoc @@ -1084,7 +1084,7 @@ open class SecurityConfig { <3> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role <4> Any other request that doesn't match the rules above, will require authentication -The `securityMatcher(s)` and `requestMatcher(s)` methods will decide which `RequestMatcher` implementation fits best for your application: If {spring-framework-reference-url}web.html#spring-web[Spring MVC] is in the classpath, then javadoc:org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher[] will be used, otherwise, javadoc:org.springframework.security.web.util.matcher.AntPathRequestMatcher[] will be used. +The `securityMatcher(s)` and `requestMatcher(s)` methods will construct ``RequestMatcher``s using a javadoc:org.springframework.security.web.util.matcher.PathPatternRequestMatcher.Builder[] bean, if available. You can read more about the Spring MVC integration xref:servlet/integrations/mvc.adoc[here]. If you want to use a specific `RequestMatcher`, just pass an implementation to the `securityMatcher` and/or `requestMatcher` methods: @@ -1095,7 +1095,7 @@ Java:: + [source,java,role="primary"] ---- -import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; <1> +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.withDefaults; <1> import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher; @Configuration @@ -1107,7 +1107,7 @@ public class SecurityConfig { http .securityMatcher(antMatcher("/api/**")) <2> .authorizeHttpRequests((authorize) -> authorize - .requestMatchers(antMatcher("/api/user/**")).hasRole("USER") <3> + .requestMatchers(withDefaults().matcher("/api/user/**")).hasRole("USER") <3> .requestMatchers(regexMatcher("/api/admin/.*")).hasRole("ADMIN") <4> .requestMatchers(new MyCustomRequestMatcher()).hasRole("SUPERVISOR") <5> .anyRequest().authenticated() @@ -1130,7 +1130,7 @@ Kotlin:: + [source,kotlin,role="secondary"] ---- -import org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher <1> +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.withDefaults <1> import org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher @Configuration @@ -1142,7 +1142,7 @@ open class SecurityConfig { http { securityMatcher(antMatcher("/api/**")) <2> authorizeHttpRequests { - authorize(antMatcher("/api/user/**"), hasRole("USER")) <3> + authorize(withDefaults().matcher("/api/user/**"), hasRole("USER")) <3> authorize(regexMatcher("/api/admin/**"), hasRole("ADMIN")) <4> authorize(MyCustomRequestMatcher(), hasRole("SUPERVISOR")) <5> authorize(anyRequest, authenticated) @@ -1155,9 +1155,9 @@ open class SecurityConfig { ---- ====== -<1> Import the static factory methods from `AntPathRequestMatcher` and `RegexRequestMatcher` to create `RequestMatcher` instances. -<2> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`, using `AntPathRequestMatcher` -<3> Allow access to URLs that start with `/api/user/` to users with the `USER` role, using `AntPathRequestMatcher` +<1> Import the static factory methods from `PathPatternRequestMatcher` and `RegexRequestMatcher` to create `RequestMatcher` instances. +<2> Configure `HttpSecurity` to only be applied to URLs that start with `/api/`, using `PathPatternRequestMatcher` +<3> Allow access to URLs that start with `/api/user/` to users with the `USER` role, using `PathPatternRequestMatcher` <4> Allow access to URLs that start with `/api/admin/` to users with the `ADMIN` role, using `RegexRequestMatcher` <5> Allow access to URLs that match the `MyCustomRequestMatcher` to users with the `SUPERVISOR` role, using a custom `RequestMatcher` diff --git a/docs/modules/ROOT/pages/servlet/configuration/java.adoc b/docs/modules/ROOT/pages/servlet/configuration/java.adoc index a3c09f57323..193ce75c647 100644 --- a/docs/modules/ROOT/pages/servlet/configuration/java.adoc +++ b/docs/modules/ROOT/pages/servlet/configuration/java.adoc @@ -132,7 +132,7 @@ public class MvcWebApplicationInitializer extends ---- The reason for this is that Spring Security needs to be able to inspect some Spring MVC configuration in order to appropriately configure xref:servlet/authorization/authorize-http-requests.adoc#authorizing-endpoints[underlying request matchers], so they need to be in the same application context. -Placing Spring Security in `getRootConfigClasses` places it into a parent application context that may not be able to find Spring MVC's `HandlerMappingIntrospector`. +Placing Spring Security in `getRootConfigClasses` places it into a parent application context that may not be able to find Spring MVC's `PathPatternParser`. ==== Configuring for Multiple Spring MVC Dispatchers diff --git a/docs/modules/ROOT/pages/servlet/exploits/csrf.adoc b/docs/modules/ROOT/pages/servlet/exploits/csrf.adoc index f02350dc6d1..33834f12b25 100644 --- a/docs/modules/ROOT/pages/servlet/exploits/csrf.adoc +++ b/docs/modules/ROOT/pages/servlet/exploits/csrf.adoc @@ -1276,7 +1276,7 @@ XML:: - + @@ -1387,7 +1387,7 @@ public class SecurityConfig { http // ... .logout((logout) -> logout - .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/logout")) ); return http.build(); } @@ -1409,7 +1409,7 @@ class SecurityConfig { http { // ... logout { - logoutRequestMatcher = AntPathRequestMatcher("/logout") + logoutRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/logout") } } return http.build() diff --git a/docs/modules/ROOT/pages/servlet/exploits/firewall.adoc b/docs/modules/ROOT/pages/servlet/exploits/firewall.adoc index 29dd8fcf93c..e4978ea6edf 100644 --- a/docs/modules/ROOT/pages/servlet/exploits/firewall.adoc +++ b/docs/modules/ROOT/pages/servlet/exploits/firewall.adoc @@ -24,7 +24,7 @@ It is, therefore, essential that a `FilterChainProxy` is used to manage the secu Note that the `servletPath` and `pathInfo` values are decoded by the container, so your application should not have any valid paths that contain semi-colons, as these parts are removed for matching purposes. As mentioned earlier, the default strategy is to use Ant-style paths for matching, and this is likely to be the best choice for most users. -The strategy is implemented in the class `AntPathRequestMatcher`, which uses Spring's `AntPathMatcher` to perform a case-insensitive match of the pattern against the concatenated `servletPath` and `pathInfo`, ignoring the `queryString`. +The strategy is implemented in the class `PathPatternRequestMatcher`, which uses Spring's `PathPattern` to perform a case-insensitive match of the pattern against the concatenated `servletPath` and `pathInfo`, ignoring the `queryString`. If you need a more powerful matching strategy, you can use regular expressions. The strategy implementation is then `RegexRequestMatcher`. diff --git a/docs/modules/ROOT/pages/servlet/exploits/headers.adoc b/docs/modules/ROOT/pages/servlet/exploits/headers.adoc index 5b12c92f747..a36dd804cc7 100644 --- a/docs/modules/ROOT/pages/servlet/exploits/headers.adoc +++ b/docs/modules/ROOT/pages/servlet/exploits/headers.adoc @@ -1218,7 +1218,7 @@ public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - RequestMatcher matcher = new AntPathRequestMatcher("/login"); + RequestMatcher matcher = PathPatternRequestMatcher.withDefaults().matcher("/login"); DelegatingRequestMatcherHeaderWriter headerWriter = new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter()); http @@ -1248,7 +1248,7 @@ XML:: - @@ -1268,7 +1268,7 @@ class SecurityConfig { @Bean open fun filterChain(http: HttpSecurity): SecurityFilterChain { - val matcher: RequestMatcher = AntPathRequestMatcher("/login") + val matcher: RequestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/login") val headerWriter = DelegatingRequestMatcherHeaderWriter(matcher, XFrameOptionsHeaderWriter()) http { headers { diff --git a/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc b/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc index a4827bac7b1..6ed05712fea 100644 --- a/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc +++ b/docs/modules/ROOT/pages/servlet/integrations/websocket.adoc @@ -698,7 +698,7 @@ If we use XML-based configuration, we can use thexref:servlet/appendix/namespace - + diff --git a/etc/checkstyle/checkstyle.xml b/etc/checkstyle/checkstyle.xml index 9b4b616eb0e..297f8a84428 100644 --- a/etc/checkstyle/checkstyle.xml +++ b/etc/checkstyle/checkstyle.xml @@ -18,7 +18,8 @@ - + + diff --git a/itest/context/spring-security-itest-context.gradle b/itest/context/spring-security-itest-context.gradle index c278418f74b..29e83a6161f 100644 --- a/itest/context/spring-security-itest-context.gradle +++ b/itest/context/spring-security-itest-context.gradle @@ -9,7 +9,7 @@ dependencies { implementation 'org.springframework:spring-context' implementation 'org.springframework:spring-tx' - testImplementation project(':spring-security-web') + testImplementation project(path: ':spring-security-web', configuration: 'tests') testImplementation 'jakarta.servlet:jakarta.servlet-api' testImplementation 'org.springframework:spring-web' testImplementation "org.assertj:assertj-core" diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java b/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java index aab6742b810..cf869c7ef30 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java @@ -43,9 +43,7 @@ public class HttpNamespaceWithMultipleInterceptorsTests { @Test public void requestThatIsMatchedByDefaultInterceptorIsAllowed() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setMethod("GET"); - request.setServletPath("/somefile.html"); + MockHttpServletRequest request = TestMockHttpServletRequests.get("/somefile.html").build(); request.setSession(createAuthenticatedSession("ROLE_0", "ROLE_1", "ROLE_2")); MockHttpServletResponse response = new MockHttpServletResponse(); this.fcp.doFilter(request, response, new MockFilterChain()); @@ -54,10 +52,7 @@ public void requestThatIsMatchedByDefaultInterceptorIsAllowed() throws Exception @Test public void securedUrlAccessIsRejectedWithoutRequiredRole() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setMethod("GET"); - - request.setServletPath("/secure/somefile.html"); + MockHttpServletRequest request = TestMockHttpServletRequests.get("/secure/somefile.html").build(); request.setSession(createAuthenticatedSession("ROLE_0")); MockHttpServletResponse response = new MockHttpServletResponse(); this.fcp.doFilter(request, response, new MockFilterChain()); diff --git a/itest/context/src/integration-test/resources/filter-chain-performance-app-context.xml b/itest/context/src/integration-test/resources/filter-chain-performance-app-context.xml index 7b6ac0c6561..8311103464e 100644 --- a/itest/context/src/integration-test/resources/filter-chain-performance-app-context.xml +++ b/itest/context/src/integration-test/resources/filter-chain-performance-app-context.xml @@ -11,13 +11,13 @@ http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd"> - + - + diff --git a/itest/web/src/integration-test/resources/spring/http-security-concurrency.xml b/itest/web/src/integration-test/resources/spring/http-security-concurrency.xml index 310f1bedfed..7ba9243c798 100644 --- a/itest/web/src/integration-test/resources/spring/http-security-concurrency.xml +++ b/itest/web/src/integration-test/resources/spring/http-security-concurrency.xml @@ -47,6 +47,6 @@ - + diff --git a/oauth2/oauth2-client/spring-security-oauth2-client.gradle b/oauth2/oauth2-client/spring-security-oauth2-client.gradle index 93bab342cf7..11b6c91f0ab 100644 --- a/oauth2/oauth2-client/spring-security-oauth2-client.gradle +++ b/oauth2/oauth2-client/spring-security-oauth2-client.gradle @@ -18,6 +18,7 @@ dependencies { testImplementation project(path: ':spring-security-oauth2-core', configuration: 'tests') testImplementation project(path: ':spring-security-oauth2-jose', configuration: 'tests') + testImplementation project(path: ':spring-security-web', configuration: 'tests') testImplementation 'com.squareup.okhttp3:mockwebserver' testImplementation 'io.micrometer:context-propagation' testImplementation 'io.projectreactor.netty:reactor-netty' diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java index 1382a0368f8..92a170394a9 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java @@ -44,6 +44,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.entry; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * Tests for {@link DefaultOAuth2AuthorizationRequestResolver}. @@ -123,8 +125,7 @@ public void setAuthorizationRequestCustomizerWhenNullThenThrowIllegalArgumentExc @Test public void resolveWhenNotAuthorizationRequestThenDoesNotResolve() { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest).isNull(); } @@ -133,7 +134,7 @@ public void resolveWhenNotAuthorizationRequestThenDoesNotResolve() { @Test public void resolveWhenNotAuthorizationRequestThenRequestBodyNotConsumed() throws IOException { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri); + MockHttpServletRequest request = post(requestUri).build(); request.setContent("foo".getBytes(StandardCharsets.UTF_8)); request.setCharacterEncoding(StandardCharsets.UTF_8.name()); HttpServletRequest spyRequest = Mockito.spy(request); @@ -151,8 +152,7 @@ public void resolveWhenAuthorizationRequestWithInvalidClientThenThrowIllegalArgu ClientRegistration clientRegistration = this.registration1; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId() + "-invalid"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); // @formatter:off assertThatIllegalArgumentException() .isThrownBy(() -> this.resolver.resolve(request)) @@ -164,8 +164,7 @@ public void resolveWhenAuthorizationRequestWithInvalidClientThenThrowIllegalArgu public void resolveWhenAuthorizationRequestWithValidClientThenResolves() { ClientRegistration clientRegistration = this.registration1; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest).isNotNull(); assertThat(authorizationRequest.getAuthorizationUri()) @@ -191,8 +190,7 @@ public void resolveWhenAuthorizationRequestWithValidClientThenResolves() { public void resolveWhenClientAuthorizationRequiredExceptionAvailableThenResolves() { ClientRegistration clientRegistration = this.registration2; String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request, clientRegistration.getRegistrationId()); assertThat(authorizationRequest).isNotNull(); @@ -204,8 +202,7 @@ public void resolveWhenClientAuthorizationRequiredExceptionAvailableThenResolves public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenRedirectUriExpanded() { ClientRegistration clientRegistration = this.registration2; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); assertThat(authorizationRequest.getRedirectUri()) @@ -216,9 +213,7 @@ public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenRedirectUriEx public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenHttpRedirectUriWithExtraVarsExpanded() { ClientRegistration clientRegistration = this.fineRedirectUriTemplateRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServerPort(8080); - request.setServletPath(requestUri); + MockHttpServletRequest request = get("localhost:8080" + requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); assertThat(authorizationRequest.getRedirectUri()) @@ -229,10 +224,7 @@ public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenHttpRedirectU public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenHttpsRedirectUriWithExtraVarsExpanded() { ClientRegistration clientRegistration = this.fineRedirectUriTemplateRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("https"); - request.setServerPort(8081); - request.setServletPath(requestUri); + MockHttpServletRequest request = get("https://localhost:8081" + requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); assertThat(authorizationRequest.getRedirectUri()) @@ -243,10 +235,7 @@ public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenHttpsRedirect public void resolveWhenAuthorizationRequestIncludesPort80ThenExpandedRedirectUriWithExtraVarsExcludesPort() { ClientRegistration clientRegistration = this.fineRedirectUriTemplateRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("http"); - request.setServerPort(80); - request.setServletPath(requestUri); + MockHttpServletRequest request = get("http://localhost" + requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); assertThat(authorizationRequest.getRedirectUri()) @@ -257,10 +246,7 @@ public void resolveWhenAuthorizationRequestIncludesPort80ThenExpandedRedirectUri public void resolveWhenAuthorizationRequestIncludesPort443ThenExpandedRedirectUriWithExtraVarsExcludesPort() { ClientRegistration clientRegistration = this.fineRedirectUriTemplateRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("https"); - request.setServerPort(443); - request.setServletPath(requestUri); + MockHttpServletRequest request = get("https://localhost:443" + requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); assertThat(authorizationRequest.getRedirectUri()) @@ -271,10 +257,7 @@ public void resolveWhenAuthorizationRequestIncludesPort443ThenExpandedRedirectUr public void resolveWhenAuthorizationRequestHasNoPortThenInvalidUrlException() { ClientRegistration clientRegistration = this.fineRedirectUriTemplateRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("https"); - request.setServerPort(-1); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).port(-1).build(); assertThatExceptionOfType(InvalidUrlException.class).isThrownBy(() -> this.resolver.resolve(request)); } @@ -283,9 +266,7 @@ public void resolveWhenAuthorizationRequestHasNoPortThenInvalidUrlException() { public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenRedirectUriExpandedExcludesQueryString() { ClientRegistration clientRegistration = this.registration2; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.setQueryString("foo=bar"); + MockHttpServletRequest request = get(requestUri + "?foo=bar").build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); assertThat(authorizationRequest.getRedirectUri()) @@ -296,11 +277,7 @@ public void resolveWhenAuthorizationRequestRedirectUriTemplatedThenRedirectUriEx public void resolveWhenAuthorizationRequestIncludesPort80ThenExpandedRedirectUriExcludesPort() { ClientRegistration clientRegistration = this.registration1; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("http"); - request.setServerName("localhost"); - request.setServerPort(80); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" @@ -312,11 +289,7 @@ public void resolveWhenAuthorizationRequestIncludesPort80ThenExpandedRedirectUri public void resolveWhenAuthorizationRequestIncludesPort443ThenExpandedRedirectUriExcludesPort() { ClientRegistration clientRegistration = this.registration1; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("https"); - request.setServerName("example.com"); - request.setServerPort(443); - request.setServletPath(requestUri); + MockHttpServletRequest request = get("https://example.com:443" + requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" @@ -328,8 +301,7 @@ public void resolveWhenAuthorizationRequestIncludesPort443ThenExpandedRedirectUr public void resolveWhenClientAuthorizationRequiredExceptionAvailableThenRedirectUriIsAuthorize() { ClientRegistration clientRegistration = this.registration1; String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request, clientRegistration.getRegistrationId()); assertThat(authorizationRequest.getAuthorizationRequestUri()) @@ -342,8 +314,7 @@ public void resolveWhenClientAuthorizationRequiredExceptionAvailableThenRedirect public void resolveWhenAuthorizationRequestOAuth2LoginThenRedirectUriIsLogin() { ClientRegistration clientRegistration = this.registration2; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id-2&" @@ -355,9 +326,7 @@ public void resolveWhenAuthorizationRequestOAuth2LoginThenRedirectUriIsLogin() { public void resolveWhenAuthorizationRequestHasActionParameterAuthorizeThenRedirectUriIsAuthorize() { ClientRegistration clientRegistration = this.registration1; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.addParameter("action", "authorize"); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).param("action", "authorize").build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" @@ -369,9 +338,7 @@ public void resolveWhenAuthorizationRequestHasActionParameterAuthorizeThenRedire public void resolveWhenAuthorizationRequestHasActionParameterLoginThenRedirectUriIsLogin() { ClientRegistration clientRegistration = this.registration2; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.addParameter("action", "login"); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).param("action", "login").build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id-2&" @@ -383,8 +350,7 @@ public void resolveWhenAuthorizationRequestHasActionParameterLoginThenRedirectUr public void resolveWhenAuthorizationRequestWithValidPublicClientThenResolves() { ClientRegistration clientRegistration = this.publicClientRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest).isNotNull(); assertThat(authorizationRequest.getAuthorizationUri()) @@ -420,15 +386,13 @@ public void resolveWhenAuthorizationRequestApplyPkceToConfidentialClientsThenApp ClientRegistration clientRegistration = this.registration1; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertPkceApplied(authorizationRequest, clientRegistration); clientRegistration = this.registration2; requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + request = get(requestUri).build(); authorizationRequest = this.resolver.resolve(request); assertPkceApplied(authorizationRequest, clientRegistration); } @@ -447,15 +411,13 @@ public void resolveWhenAuthorizationRequestApplyPkceToSpecificConfidentialClient ClientRegistration clientRegistration = this.registration1; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertPkceApplied(authorizationRequest, clientRegistration); clientRegistration = this.registration2; requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + request = get(requestUri).build(); authorizationRequest = this.resolver.resolve(request); assertPkceNotApplied(authorizationRequest, clientRegistration); } @@ -491,8 +453,7 @@ private void assertPkceNotApplied(OAuth2AuthorizationRequest authorizationReques public void resolveWhenAuthenticationRequestWithValidOidcClientThenResolves() { ClientRegistration clientRegistration = this.oidcRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest).isNotNull(); assertThat(authorizationRequest.getAuthorizationUri()) @@ -524,8 +485,7 @@ public void resolveWhenAuthenticationRequestWithValidOidcClientThenResolves() { public void resolveWhenAuthorizationRequestCustomizerRemovesNonceThenQueryExcludesNonce() { ClientRegistration clientRegistration = this.oidcRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); this.resolver.setAuthorizationRequestCustomizer( (builder) -> builder.additionalParameters((params) -> params.remove(OidcParameterNames.NONCE)) .attributes((attrs) -> attrs.remove(OidcParameterNames.NONCE))); @@ -543,8 +503,7 @@ public void resolveWhenAuthorizationRequestCustomizerRemovesNonceThenQueryExclud public void resolveWhenAuthorizationRequestCustomizerAddsParameterThenQueryIncludesParameter() { ClientRegistration clientRegistration = this.oidcRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); this.resolver.setAuthorizationRequestCustomizer((builder) -> builder.authorizationRequestUri((uriBuilder) -> { uriBuilder.queryParam("param1", "value1"); return uriBuilder.build(); @@ -561,8 +520,7 @@ public void resolveWhenAuthorizationRequestCustomizerAddsParameterThenQueryInclu public void resolveWhenAuthorizationRequestCustomizerOverridesParameterThenQueryIncludesParameter() { ClientRegistration clientRegistration = this.oidcRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); this.resolver.setAuthorizationRequestCustomizer((builder) -> builder.parameters((params) -> { params.put("appid", params.get("client_id")); params.remove("client_id"); @@ -579,8 +537,7 @@ public void resolveWhenAuthorizationRequestNoProvideAuthorizationRequestBaseUri( OAuth2AuthorizationRequestResolver resolver = new DefaultOAuth2AuthorizationRequestResolver( this.clientRegistrationRepository); String requestUri = this.authorizationRequestBaseUri + "/" + this.registration2.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()) .isEqualTo("http://localhost/login/oauth2/code/" + this.registration2.getRegistrationId()); @@ -590,8 +547,7 @@ public void resolveWhenAuthorizationRequestNoProvideAuthorizationRequestBaseUri( public void resolveWhenAuthorizationRequestProvideCodeChallengeMethod() { ClientRegistration clientRegistration = this.pkceClientRegistration; String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAdditionalParameters().containsKey(PkceParameterNames.CODE_CHALLENGE_METHOD)) .isTrue(); diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java index a6f1f9bc964..440b3a6383e 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java @@ -72,6 +72,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link OAuth2AuthorizationCodeGrantFilter}. @@ -154,8 +155,7 @@ public void setRequestCacheWhenRequestCacheIsNullThenThrowIllegalArgumentExcepti @Test public void doFilterWhenNotAuthorizationResponseThenNotProcessed() throws Exception { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); // NOTE: A valid Authorization Response contains either a 'code' or 'error' // parameter. MockHttpServletResponse response = new MockHttpServletResponse(); @@ -328,8 +328,7 @@ public void doFilterWhenCustomSecurityContextHolderStrategyThenUses() throws Exc @Test public void doFilterWhenAuthorizationSucceedsAndHasSavedRequestThenRedirectToSavedRequest() throws Exception { String requestUri = "/saved-request"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); RequestCache requestCache = new HttpSessionRequestCache(); requestCache.saveRequest(request, response); @@ -430,8 +429,7 @@ private static MockHttpServletRequest createAuthorizationRequest(String requestU private static MockHttpServletRequest createAuthorizationRequest(String requestUri, Map parameters) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); if (!CollectionUtils.isEmpty(parameters)) { parameters.forEach(request::addParameter); request.setQueryString(parameters.entrySet() diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java index 59676b14619..bc51ba9e7bb 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java @@ -55,6 +55,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link OAuth2AuthorizationRequestRedirectFilter}. @@ -127,8 +128,7 @@ public void setAuthenticationFailureHandlerIsNullThenThrowIllegalArgumentExcepti @Test public void doFilterWhenNotAuthorizationRequestThenNextFilter() throws Exception { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.filter.doFilter(request, response, filterChain); @@ -139,8 +139,7 @@ public void doFilterWhenNotAuthorizationRequestThenNextFilter() throws Exception public void doFilterWhenAuthorizationRequestWithInvalidClientThenStatusInternalServerError() throws Exception { String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + this.registration1.getRegistrationId() + "-invalid"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.filter.doFilter(request, response, filterChain); @@ -154,8 +153,7 @@ public void doFilterWhenAuthorizationRequestWithInvalidClientAndCustomFailureHan throws Exception { String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + this.registration1.getRegistrationId() + "-invalid"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.filter.setAuthenticationFailureHandler((request1, response1, ex) -> { @@ -178,8 +176,7 @@ public void doFilterWhenAuthorizationRequestWithInvalidClientAndCustomFailureHan public void doFilterWhenAuthorizationRequestOAuth2LoginThenRedirectForAuthorization() throws Exception { String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + this.registration1.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.filter.doFilter(request, response, filterChain); @@ -193,8 +190,7 @@ public void doFilterWhenAuthorizationRequestOAuth2LoginThenRedirectForAuthorizat public void doFilterWhenAuthorizationRequestOAuth2LoginThenAuthorizationRequestSaved() throws Exception { String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + this.registration2.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); AuthorizationRequestRepository authorizationRequestRepository = mock( @@ -212,8 +208,7 @@ public void doFilterWhenCustomAuthorizationRequestBaseUriThenRedirectForAuthoriz this.filter = new OAuth2AuthorizationRequestRedirectFilter(this.clientRegistrationRepository, authorizationRequestBaseUri); String requestUri = authorizationRequestBaseUri + "/" + this.registration1.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.filter.doFilter(request, response, filterChain); @@ -227,8 +222,7 @@ public void doFilterWhenCustomAuthorizationRequestBaseUriThenRedirectForAuthoriz public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExceptionThrownThenRedirectForAuthorization() throws Exception { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); willThrow(new ClientAuthorizationRequiredException(this.registration1.getRegistrationId())).given(filterChain) @@ -245,8 +239,7 @@ public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExc public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExceptionThrownButAuthorizationRequestNotResolvedThenStatusInternalServerError() throws Exception { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); willThrow(new ClientAuthorizationRequiredException(this.registration1.getRegistrationId())).given(filterChain) @@ -266,8 +259,7 @@ public void doFilterWhenAuthorizationRequestAndAdditionalParametersProvidedThenA throws Exception { String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + this.registration1.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); request.addParameter("idp", "https://other.provider.com"); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); @@ -295,8 +287,7 @@ public void doFilterWhenAuthorizationRequestAndCustomAuthorizationRequestUriSetT throws Exception { String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + this.registration1.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); String loginHintParamName = "login_hint"; request.addParameter(loginHintParamName, "user@provider.com"); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -335,8 +326,7 @@ public void doFilterWhenCustomAuthorizationRedirectStrategySetThenCustomAuthoriz throws Exception { String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + this.registration1.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); RedirectStrategy customRedirectStrategy = (httpRequest, httpResponse, url) -> { @@ -363,8 +353,7 @@ public void doFilterWhenCustomAuthorizationRedirectStrategySetThenCustomAuthoriz public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExceptionThrownThenSaveRequestBeforeCommitted() throws Exception { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); willAnswer((invocation) -> assertThat((invocation.getArgument(1)).isCommitted()).isFalse()) diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java index 3dee3c0cc03..5e7b5a42112 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java @@ -69,6 +69,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link OAuth2LoginAuthenticationFilter}. @@ -163,8 +164,7 @@ public void setAuthenticationResultConverterWhenAuthenticationResultConverterIsN @Test public void doFilterWhenNotAuthorizationResponseThenNextFilter() throws Exception { String requestUri = "/path"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.filter.doFilter(request, response, filterChain); @@ -176,8 +176,7 @@ public void doFilterWhenNotAuthorizationResponseThenNextFilter() throws Exceptio @Test public void doFilterWhenAuthorizationResponseInvalidThenInvalidRequestError() throws Exception { String requestUri = "/login/oauth2/code/" + this.registration1.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); + MockHttpServletRequest request = get(requestUri).build(); // NOTE: // A valid Authorization Response contains either a 'code' or 'error' parameter. // Don't set it to force an invalid Authorization Response. @@ -198,10 +197,9 @@ public void doFilterWhenAuthorizationResponseInvalidThenInvalidRequestError() th public void doFilterWhenAuthorizationResponseAuthorizationRequestNotFoundThenAuthorizationRequestNotFoundError() throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, "state"); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, "state") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.filter.doFilter(request, response, filterChain); @@ -221,10 +219,9 @@ public void doFilterWhenAuthorizationResponseClientRegistrationNotFoundThenClien throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, "state"); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); // @formatter:off @@ -258,10 +255,9 @@ public void doFilterWhenAuthorizationResponseClientRegistrationNotFoundThenClien public void doFilterWhenAuthorizationResponseValidThenAuthorizationRequestRemoved() throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, state); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.setUpAuthorizationRequest(request, response, this.registration2, state); @@ -274,10 +270,9 @@ public void doFilterWhenAuthorizationResponseValidThenAuthorizationRequestRemove public void doFilterWhenAuthorizationResponseValidThenAuthorizedClientSaved() throws Exception { String requestUri = "/login/oauth2/code/" + this.registration1.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, state); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.setUpAuthorizationRequest(request, response, this.registration1, state); @@ -300,10 +295,9 @@ public void doFilterWhenCustomFilterProcessesUrlThenFilterProcesses() throws Exc this.filter.setAuthenticationManager(this.authenticationManager); String requestUri = "/login/oauth2/custom/" + this.registration2.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, state); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.setUpAuthorizationRequest(request, response, this.registration2, state); @@ -319,13 +313,9 @@ public void doFilterWhenAuthorizationResponseHasDefaultPort80ThenRedirectUriMatc throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("http"); - request.setServerName("localhost"); - request.setServerPort(80); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, "state"); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.setUpAuthorizationRequest(request, response, this.registration2, state); @@ -350,13 +340,10 @@ public void doFilterWhenAuthorizationResponseHasDefaultPort443ThenRedirectUriMat throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("https"); - request.setServerName("example.com"); - request.setServerPort(443); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, "state"); + MockHttpServletRequest request = get("https://example.com:443" + requestUri) + .param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.setUpAuthorizationRequest(request, response, this.registration2, state); @@ -381,13 +368,10 @@ public void doFilterWhenAuthorizationResponseHasNonDefaultPortThenRedirectUriMat throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setScheme("https"); - request.setServerName("example.com"); - request.setServerPort(9090); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, "state"); + MockHttpServletRequest request = get("https://example.com:9090" + requestUri) + .param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); this.setUpAuthorizationRequest(request, response, this.registration2, state); @@ -411,10 +395,9 @@ public void doFilterWhenAuthorizationResponseHasNonDefaultPortThenRedirectUriMat public void attemptAuthenticationShouldSetAuthenticationDetailsOnAuthenticationResult() throws Exception { String requestUri = "/login/oauth2/code/" + this.registration1.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, state); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); WebAuthenticationDetails webAuthenticationDetails = mock(WebAuthenticationDetails.class); given(this.authenticationDetailsSource.buildDetails(any())).willReturn(webAuthenticationDetails); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -430,10 +413,9 @@ public void attemptAuthenticationWhenAuthenticationResultIsNullThenIllegalArgume this.filter.setAuthenticationResultConverter((authentication) -> null); String requestUri = "/login/oauth2/code/" + this.registration1.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, state); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); this.setUpAuthorizationRequest(request, response, this.registration1, state); this.setUpAuthenticationResult(this.registration1); @@ -448,10 +430,9 @@ public void attemptAuthenticationWhenAuthenticationResultConverterSetThenUsed() authentication.getAuthorities(), authentication.getClientRegistration().getRegistrationId())); String requestUri = "/login/oauth2/code/" + this.registration1.getRegistrationId(); String state = "state"; - MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); - request.setServletPath(requestUri); - request.addParameter(OAuth2ParameterNames.CODE, "code"); - request.addParameter(OAuth2ParameterNames.STATE, state); + MockHttpServletRequest request = get(requestUri).param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, state) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); this.setUpAuthorizationRequest(request, response, this.registration1, state); this.setUpAuthenticationResult(this.registration1); diff --git a/saml2/saml2-service-provider/spring-security-saml2-service-provider.gradle b/saml2/saml2-service-provider/spring-security-saml2-service-provider.gradle index b05c1bbd577..64511c5079c 100644 --- a/saml2/saml2-service-provider/spring-security-saml2-service-provider.gradle +++ b/saml2/saml2-service-provider/spring-security-saml2-service-provider.gradle @@ -108,6 +108,7 @@ dependencies { optional 'com.fasterxml.jackson.core:jackson-databind' optional 'org.springframework:spring-jdbc' + testImplementation project(path: ':spring-security-web', configuration: 'tests') testImplementation 'com.squareup.okhttp3:mockwebserver' testImplementation "org.assertj:assertj-core" testImplementation "org.skyscreamer:jsonassert" diff --git a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml4AuthenticationTokenConverterTests.java b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml4AuthenticationTokenConverterTests.java index 57f4221260d..1635b4aa53f 100644 --- a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml4AuthenticationTokenConverterTests.java +++ b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml4AuthenticationTokenConverterTests.java @@ -42,6 +42,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.util.StreamUtils; import org.springframework.web.util.UriUtils; @@ -216,15 +217,11 @@ private String getSsoCircleEncodedXml() throws IOException { } private MockHttpServletRequest post(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("POST", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.post(uri).build(); } private MockHttpServletRequest get(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.get(uri).build(); } private T signed(T toSign) { diff --git a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSamlAuthenticationTokenConverterTests.java b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSamlAuthenticationTokenConverterTests.java index abcf3a4c78f..ffb21968363 100644 --- a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSamlAuthenticationTokenConverterTests.java +++ b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/OpenSamlAuthenticationTokenConverterTests.java @@ -42,6 +42,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.util.StreamUtils; import org.springframework.web.util.UriUtils; @@ -216,15 +217,11 @@ private String getSsoCircleEncodedXml() throws IOException { } private MockHttpServletRequest post(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("POST", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.post(uri).build(); } private MockHttpServletRequest get(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.get(uri).build(); } private T signed(T toSign) { diff --git a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml4AuthenticationRequestResolverTests.java b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml4AuthenticationRequestResolverTests.java index 2716f0befd6..a1a172a8edc 100644 --- a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml4AuthenticationRequestResolverTests.java +++ b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml4AuthenticationRequestResolverTests.java @@ -28,7 +28,7 @@ import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -88,10 +88,11 @@ void resolveWhenCustomRelayStateThenUses() { @Test void resolveWhenCustomAuthenticationUrlTHenUses() { + PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults(); RelyingPartyRegistrationResolver relyingParties = mock(RelyingPartyRegistrationResolver.class); given(relyingParties.resolve(any(), any())).willReturn(this.registration); OpenSaml4AuthenticationRequestResolver resolver = new OpenSaml4AuthenticationRequestResolver(relyingParties); - resolver.setRequestMatcher(new AntPathRequestMatcher("/custom/authentication/{registrationId}")); + resolver.setRequestMatcher(builder.matcher("/custom/authentication/{registrationId}")); Saml2RedirectAuthenticationRequest authnRequest = resolver .resolve(givenRequest("/custom/authentication/registration-id")); @@ -102,9 +103,7 @@ void resolveWhenCustomAuthenticationUrlTHenUses() { } private MockHttpServletRequest givenRequest(String path) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", path); - request.setServletPath(path); - return request; + return new MockHttpServletRequest("GET", path); } } diff --git a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutRequestValidatorParametersResolverTests.java b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutRequestValidatorParametersResolverTests.java index c7aeb8b8785..cdf9cd77126 100644 --- a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutRequestValidatorParametersResolverTests.java +++ b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutRequestValidatorParametersResolverTests.java @@ -36,6 +36,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -135,15 +136,11 @@ void saml2LogoutRegistrationIdResolveWhenNoMatchingRegistrationIdThenSaml2Except } private MockHttpServletRequest post(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("POST", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.post(uri).build(); } private MockHttpServletRequest get(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.get(uri).build(); } private String serialize(XMLObject object) { diff --git a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestValidatorParametersResolverTests.java b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestValidatorParametersResolverTests.java index b57db0a8957..e036b749cc3 100644 --- a/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestValidatorParametersResolverTests.java +++ b/saml2/saml2-service-provider/src/opensaml4Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestValidatorParametersResolverTests.java @@ -36,6 +36,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -135,15 +136,11 @@ void saml2LogoutRegistrationIdResolveWhenNoMatchingRegistrationIdThenSaml2Except } private MockHttpServletRequest post(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("POST", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.post(uri).build(); } private MockHttpServletRequest get(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.get(uri).build(); } private String serialize(XMLObject object) { diff --git a/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml5AuthenticationTokenConverterTests.java b/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml5AuthenticationTokenConverterTests.java index 1c35ec58e36..dcf7617c6bd 100644 --- a/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml5AuthenticationTokenConverterTests.java +++ b/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/OpenSaml5AuthenticationTokenConverterTests.java @@ -42,6 +42,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.util.StreamUtils; import org.springframework.web.util.UriUtils; @@ -216,15 +217,11 @@ private String getSsoCircleEncodedXml() throws IOException { } private MockHttpServletRequest post(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("POST", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.post(uri).build(); } private MockHttpServletRequest get(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.get(uri).build(); } private T signed(T toSign) { diff --git a/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml5AuthenticationRequestResolverTests.java b/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml5AuthenticationRequestResolverTests.java index bf5d059e1a3..c0163f7a106 100644 --- a/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml5AuthenticationRequestResolverTests.java +++ b/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSaml5AuthenticationRequestResolverTests.java @@ -28,7 +28,8 @@ import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -91,7 +92,8 @@ void resolveWhenCustomAuthenticationUrlTHenUses() { RelyingPartyRegistrationResolver relyingParties = mock(RelyingPartyRegistrationResolver.class); given(relyingParties.resolve(any(), any())).willReturn(this.registration); OpenSaml5AuthenticationRequestResolver resolver = new OpenSaml5AuthenticationRequestResolver(relyingParties); - resolver.setRequestMatcher(new AntPathRequestMatcher("/custom/authentication/{registrationId}")); + resolver.setRequestMatcher( + PathPatternRequestMatcher.withDefaults().matcher("/custom/authentication/{registrationId}")); Saml2RedirectAuthenticationRequest authnRequest = resolver .resolve(givenRequest("/custom/authentication/registration-id")); @@ -102,9 +104,7 @@ void resolveWhenCustomAuthenticationUrlTHenUses() { } private MockHttpServletRequest givenRequest(String path) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", path); - request.setServletPath(path); - return request; + return TestMockHttpServletRequests.get(path).build(); } } diff --git a/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml5LogoutRequestValidatorParametersResolverTests.java b/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml5LogoutRequestValidatorParametersResolverTests.java index 8ec0cef3068..af13bef179c 100644 --- a/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml5LogoutRequestValidatorParametersResolverTests.java +++ b/saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml5LogoutRequestValidatorParametersResolverTests.java @@ -36,6 +36,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -135,15 +136,11 @@ void saml2LogoutRegistrationIdResolveWhenNoMatchingRegistrationIdThenSaml2Except } private MockHttpServletRequest post(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("POST", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.post(uri).build(); } private MockHttpServletRequest get(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.get(uri).build(); } private String serialize(XMLObject object) { diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/RequestMatcherMetadataResponseResolverTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/RequestMatcherMetadataResponseResolverTests.java index 0684218ffd1..1145cca6860 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/RequestMatcherMetadataResponseResolverTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/RequestMatcherMetadataResponseResolverTests.java @@ -30,6 +30,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; +import org.springframework.security.web.servlet.TestMockHttpServletRequests; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -121,9 +122,7 @@ void resolveWhenNoRegistrationIdThenResolvesEntityIds() { } private MockHttpServletRequest get(String uri) { - MockHttpServletRequest request = new MockHttpServletRequest("GET", uri); - request.setServletPath(uri); - return request; + return TestMockHttpServletRequests.get(uri).build(); } private RelyingPartyRegistration withEntityId(String entityId) { diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java index 471ca2a8599..1d1b247d633 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java @@ -34,7 +34,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -129,7 +129,7 @@ public void doFilterWhenMatchesThenRespondsWithMetadata() throws Exception { @Test public void doFilterWhenCustomRequestMatcherThenUses() throws Exception { MockHttpServletRequest request = uri("/path"); - this.filter.setRequestMatcher(new AntPathRequestMatcher("/path")); + this.filter.setRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/path")); this.filter.doFilter(request, this.response, this.chain); verifyNoInteractions(this.chain); verify(this.repository).findByRegistrationId("path"); @@ -159,7 +159,7 @@ public void doFilterWhenResolverConstructorAndPathStartsWithRegistrationIdThenSe RelyingPartyRegistrationResolver resolver = new DefaultRelyingPartyRegistrationResolver( (id) -> this.repository.findByRegistrationId("registration-id")); this.filter = new Saml2MetadataFilter(resolver, this.resolver); - this.filter.setRequestMatcher(new AntPathRequestMatcher("/metadata")); + this.filter.setRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/metadata")); MockHttpServletRequest request = uri("/metadata"); this.filter.doFilter(request, this.response, new MockFilterChain()); verify(this.repository).findByRegistrationId("registration-id"); @@ -173,7 +173,7 @@ public void doFilterWhenRelyingPartyRegistrationRepositoryConstructorAndPathStar given(this.resolver.resolve(any(RelyingPartyRegistration.class))).willReturn("metadata"); this.filter = new Saml2MetadataFilter((id) -> this.repository.findByRegistrationId("registration-id"), this.resolver); - this.filter.setRequestMatcher(new AntPathRequestMatcher("/metadata")); + this.filter.setRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/metadata")); MockHttpServletRequest request = uri("/metadata"); this.filter.doFilter(request, this.response, new MockFilterChain()); verify(this.repository).findByRegistrationId("registration-id"); diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/Saml2WebSsoAuthenticationFilterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/Saml2WebSsoAuthenticationFilterTests.java index 9e4b4d32690..ac31a34f320 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/Saml2WebSsoAuthenticationFilterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/Saml2WebSsoAuthenticationFilterTests.java @@ -43,7 +43,7 @@ import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter; import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.authentication.WebAuthenticationDetails; -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; @@ -225,7 +225,7 @@ public void doFilterWhenPathStartsWithRegistrationIdThenAuthenticates() throws E given(this.repository.findByRegistrationId("registration-id")).willReturn(registration); given(this.authenticationManager.authenticate(authentication)).willReturn(authentication); String loginProcessingUrl = "/{registrationId}/login/saml2/sso"; - RequestMatcher matcher = new AntPathRequestMatcher(loginProcessingUrl); + RequestMatcher matcher = PathPatternRequestMatcher.withDefaults().matcher(loginProcessingUrl); DefaultRelyingPartyRegistrationResolver delegate = new DefaultRelyingPartyRegistrationResolver(this.repository); RelyingPartyRegistrationResolver resolver = (request, id) -> { String registrationId = matcher.matcher(request).getVariables().get("registrationId"); diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilterTests.java index cd4d88f62ae..d24ba9d7362 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilterTests.java @@ -46,6 +46,7 @@ import static org.mockito.BDDMockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * Tests for {@link Saml2LogoutRequestFilter} @@ -76,9 +77,8 @@ public void doFilterWhenSamlRequestThenRedirects() throws Exception { RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build(); Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_REQUEST, "request") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration); given(this.logoutRequestValidator.validate(any())).willReturn(Saml2LogoutValidatorResult.success()); @@ -105,9 +105,8 @@ public void doFilterWhenSamlRequestThenPosts() throws Exception { given(this.securityContextHolderStrategy.getContext()).willReturn(new SecurityContextImpl(authentication)); this.logoutRequestProcessingFilter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_REQUEST, "request") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration); given(this.logoutRequestValidator.validate(any())).willReturn(Saml2LogoutValidatorResult.success()); @@ -127,9 +126,7 @@ public void doFilterWhenSamlRequestThenPosts() throws Exception { public void doFilterWhenRequestMismatchesThenNoLogout() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout"); - request.setServletPath("/logout"); - request.setParameter(Saml2ParameterNames.SAML_RESPONSE, "response"); + MockHttpServletRequest request = post("/logout").param(Saml2ParameterNames.SAML_RESPONSE, "response").build(); MockHttpServletResponse response = new MockHttpServletResponse(); this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain()); verifyNoInteractions(this.logoutRequestValidator, this.logoutHandler); @@ -139,8 +136,7 @@ public void doFilterWhenRequestMismatchesThenNoLogout() throws Exception { public void doFilterWhenNoSamlRequestOrResponseThenNoLogout() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); + MockHttpServletRequest request = post("/logout/saml2/slo").build(); MockHttpServletResponse response = new MockHttpServletResponse(); this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain()); verifyNoInteractions(this.logoutRequestValidator, this.logoutHandler); @@ -153,9 +149,8 @@ public void doFilterWhenValidationFailsErrorLogoutResponseIsPosted() throws Exce .build(); Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_REQUEST, "request") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration) .samlResponse("response") @@ -182,7 +177,6 @@ public void doFilterWhenNoRelyingErrorLogoutResponseIsPosted() throws Exception Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); MockHttpServletResponse response = new MockHttpServletResponse(); RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() @@ -210,9 +204,8 @@ public void doFilterWhenNoRelyingErrorLogoutResponseIsPosted() throws Exception public void doFilterWhenInvalidBindingErrorLogoutResponseIsPosted() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_REQUEST, "request") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() .assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)) @@ -242,9 +235,8 @@ public void doFilterWhenInvalidBindingErrorLogoutResponseIsPosted() throws Excep public void doFilterWhenNoErrorResponseCanBeGeneratedThen401() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_REQUEST, "request") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() .assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)) diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilterTests.java index 5973f9589e7..77f43dad570 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilterTests.java @@ -43,6 +43,8 @@ import static org.mockito.BDDMockito.mock; import static org.mockito.BDDMockito.verify; import static org.mockito.Mockito.verifyNoInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * Tests for {@link Saml2LogoutResponseFilter} @@ -74,9 +76,8 @@ public void tearDown() { public void doFilterWhenSamlResponsePostThenLogout() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_RESPONSE, "response"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_RESPONSE, "response") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build(); given(this.relyingPartyRegistrationResolver.resolve(request, "registration-id")).willReturn(registration); @@ -94,8 +95,7 @@ public void doFilterWhenSamlResponsePostThenLogout() throws Exception { public void doFilterWhenSamlResponseRedirectThenLogout() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); + MockHttpServletRequest request = get("/logout/saml2/slo").build(); request.setParameter(Saml2ParameterNames.SAML_RESPONSE, "response"); MockHttpServletResponse response = new MockHttpServletResponse(); RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() @@ -116,9 +116,7 @@ public void doFilterWhenSamlResponseRedirectThenLogout() throws Exception { public void doFilterWhenRequestMismatchesThenNoLogout() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout"); - request.setServletPath("/logout"); - request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); + MockHttpServletRequest request = post("/logout").param(Saml2ParameterNames.SAML_REQUEST, "request").build(); MockHttpServletResponse response = new MockHttpServletResponse(); this.logoutResponseProcessingFilter.doFilterInternal(request, response, new MockFilterChain()); verifyNoInteractions(this.logoutResponseValidator, this.logoutSuccessHandler); @@ -128,8 +126,7 @@ public void doFilterWhenRequestMismatchesThenNoLogout() throws Exception { public void doFilterWhenNoSamlRequestOrResponseThenNoLogout() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); + MockHttpServletRequest request = post("/logout/saml2/slo").build(); MockHttpServletResponse response = new MockHttpServletResponse(); this.logoutResponseProcessingFilter.doFilterInternal(request, response, new MockFilterChain()); verifyNoInteractions(this.logoutResponseValidator, this.logoutSuccessHandler); @@ -139,9 +136,8 @@ public void doFilterWhenNoSamlRequestOrResponseThenNoLogout() throws Exception { public void doFilterWhenValidatorFailsThenStops() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_RESPONSE, "response"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_RESPONSE, "response") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build(); given(this.relyingPartyRegistrationResolver.resolve(request, "registration-id")).willReturn(registration); @@ -160,9 +156,8 @@ public void doFilterWhenValidatorFailsThenStops() throws Exception { public void doFilterWhenNoRelyingPartyLogoutThen401() throws Exception { Authentication authentication = new TestingAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(authentication); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo"); - request.setServletPath("/logout/saml2/slo"); - request.setParameter(Saml2ParameterNames.SAML_RESPONSE, "response"); + MockHttpServletRequest request = post("/logout/saml2/slo").param(Saml2ParameterNames.SAML_RESPONSE, "response") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() .singleLogoutServiceLocation(null) diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2RelyingPartyInitiatedLogoutSuccessHandlerTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2RelyingPartyInitiatedLogoutSuccessHandlerTests.java index 2823991574b..862ea2548c3 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2RelyingPartyInitiatedLogoutSuccessHandlerTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2RelyingPartyInitiatedLogoutSuccessHandlerTests.java @@ -39,6 +39,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.mock; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * Tests for {@link Saml2RelyingPartyInitiatedLogoutSuccessHandler} @@ -72,8 +73,7 @@ public void onLogoutSuccessWhenRedirectThenRedirectsToAssertingParty() throws Ex Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration) .samlRequest("request") .build(); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/saml2/logout"); - request.setServletPath("/saml2/logout"); + MockHttpServletRequest request = post("/saml2/logout").build(); MockHttpServletResponse response = new MockHttpServletResponse(); given(this.logoutRequestResolver.resolve(any(), any())).willReturn(logoutRequest); this.logoutRequestSuccessHandler.onLogoutSuccess(request, response, authentication); @@ -92,8 +92,7 @@ public void onLogoutSuccessWhenPostThenPostsToAssertingParty() throws Exception Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration) .samlRequest("request") .build(); - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/saml2/logout"); - request.setServletPath("/saml2/logout"); + MockHttpServletRequest request = post("/saml2/logout").build(); MockHttpServletResponse response = new MockHttpServletResponse(); given(this.logoutRequestResolver.resolve(any(), any())).willReturn(logoutRequest); this.logoutRequestSuccessHandler.onLogoutSuccess(request, response, authentication); diff --git a/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java b/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java index f1d973e5f60..93076b1408e 100644 --- a/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java @@ -41,7 +41,7 @@ import org.springframework.security.web.csrf.CsrfFilter; import org.springframework.security.web.csrf.CsrfTokenRepository; import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; -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.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -226,7 +226,7 @@ static class PartialSecurityConfig { SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // @formatter:off http - .securityMatcher(new AntPathRequestMatcher("/willnotmatchthis")); + .securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/willnotmatchthis")); return http.build(); // @formatter:on } 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 c71ea749306..46ce8d11b30 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.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 @@ private List getFilters(HttpServletRequest request) { * @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/HandlerMappingIntrospectorRequestTransformer.java b/web/src/main/java/org/springframework/security/web/access/HandlerMappingIntrospectorRequestTransformer.java deleted file mode 100644 index f78ad46a504..00000000000 --- a/web/src/main/java/org/springframework/security/web/access/HandlerMappingIntrospectorRequestTransformer.java +++ /dev/null @@ -1,98 +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.web.access; - -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; - -import jakarta.servlet.DispatcherType; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletRequestWrapper; - -import org.springframework.util.Assert; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; - -/** - * Transforms by passing it into - * {@link HandlerMappingIntrospector#setCache(HttpServletRequest)}. Before, it wraps the - * {@link HttpServletRequest} to ensure that the methods needed work since some methods by - * default throw {@link UnsupportedOperationException}. - * - * @author Rob Winch - * @deprecated please use {@link PathPatternRequestTransformer} instead - */ -@Deprecated(forRemoval = true) -public class HandlerMappingIntrospectorRequestTransformer - implements AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer { - - private final HandlerMappingIntrospector introspector; - - public HandlerMappingIntrospectorRequestTransformer(HandlerMappingIntrospector introspector) { - Assert.notNull(introspector, "introspector canot be null"); - this.introspector = introspector; - } - - @Override - public HttpServletRequest transform(HttpServletRequest request) { - CacheableRequestWrapper cacheableRequest = new CacheableRequestWrapper(request); - this.introspector.setCache(cacheableRequest); - return cacheableRequest; - } - - static final class CacheableRequestWrapper extends HttpServletRequestWrapper { - - private final Map attributes = new HashMap<>(); - - /** - * Constructs a request object wrapping the given request. - * @param request the {@link HttpServletRequest} to be wrapped. - * @throws IllegalArgumentException if the request is null - */ - CacheableRequestWrapper(HttpServletRequest request) { - super(request); - } - - @Override - public DispatcherType getDispatcherType() { - return DispatcherType.REQUEST; - } - - @Override - public Enumeration getAttributeNames() { - return Collections.enumeration(this.attributes.keySet()); - } - - @Override - public Object getAttribute(String name) { - return this.attributes.get(name); - } - - @Override - public void setAttribute(String name, Object o) { - this.attributes.put(name, o); - } - - @Override - public void removeAttribute(String name) { - this.attributes.remove(name); - } - - } - -} 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 db0f11ea601..d7954abdf0c 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 Collection getAllConfigAttributes() { @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 boolean supports(Class clazz) { 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"); + } + } diff --git a/web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java b/web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java index 16a737a9f7f..d96302acbd6 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java +++ b/web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java @@ -46,7 +46,7 @@ import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; import org.springframework.security.web.context.RequestAttributeSecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository; -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.util.Assert; import org.springframework.web.filter.GenericFilterBean; @@ -395,7 +395,7 @@ public void setAuthenticationManager(AuthenticationManager authenticationManager * @param filterProcessesUrl */ public void setFilterProcessesUrl(String filterProcessesUrl) { - setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(filterProcessesUrl)); + setRequiresAuthenticationRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(filterProcessesUrl)); } public final void setRequiresAuthenticationRequestMatcher(RequestMatcher requestMatcher) { diff --git a/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java b/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java index 335262b05cf..a7fe5fe599f 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java +++ b/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java @@ -65,11 +65,9 @@ import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.UrlUtils; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; import org.springframework.web.filter.GenericFilterBean; -import org.springframework.web.util.UrlPathHelper; /** * Switch User processing filter responsible for user context switching. @@ -129,9 +127,9 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); - private RequestMatcher exitUserMatcher = createMatcher("/logout/impersonate", true); + private RequestMatcher exitUserMatcher = createMatcher("/logout/impersonate"); - private RequestMatcher switchUserMatcher = createMatcher("/login/impersonate", true); + private RequestMatcher switchUserMatcher = createMatcher("/login/impersonate"); private String targetUrl; @@ -408,7 +406,7 @@ public void setUserDetailsService(UserDetailsService userDetailsService) { public void setExitUserUrl(String exitUserUrl) { Assert.isTrue(UrlUtils.isValidRedirectUrl(exitUserUrl), "exitUserUrl cannot be empty and must be a valid redirect URL"); - this.exitUserMatcher = createMatcher(exitUserUrl, false); + this.exitUserMatcher = createMatcher(exitUserUrl); } /** @@ -428,7 +426,7 @@ public void setExitUserMatcher(RequestMatcher exitUserMatcher) { public void setSwitchUserUrl(String switchUserUrl) { Assert.isTrue(UrlUtils.isValidRedirectUrl(switchUserUrl), "switchUserUrl cannot be empty and must be a valid redirect URL"); - this.switchUserMatcher = createMatcher(switchUserUrl, false); + this.switchUserMatcher = createMatcher(switchUserUrl); } /** @@ -547,11 +545,8 @@ public void setSecurityContextRepository(SecurityContextRepository securityConte this.securityContextRepository = securityContextRepository; } - private static RequestMatcher createMatcher(String pattern, boolean usePathPatterns) { - if (usePathPatterns) { - return PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, pattern); - } - return new AntPathRequestMatcher(pattern, "POST", true, new UrlPathHelper()); + private static RequestMatcher createMatcher(String pattern) { + return PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, pattern); } } diff --git a/web/src/main/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.java b/web/src/main/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.java deleted file mode 100644 index 51e36d28a89..00000000000 --- a/web/src/main/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2002-2022 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.web.servlet.util.matcher; - -import java.util.Map; -import java.util.Objects; - -import jakarta.servlet.http.HttpServletRequest; - -import org.springframework.http.HttpMethod; -import org.springframework.security.web.util.matcher.RequestMatcher; -import org.springframework.security.web.util.matcher.RequestVariablesExtractor; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; -import org.springframework.web.servlet.handler.MatchableHandlerMapping; -import org.springframework.web.servlet.handler.RequestMatchResult; -import org.springframework.web.util.UrlPathHelper; - -/** - * A {@link RequestMatcher} that uses Spring MVC's {@link HandlerMappingIntrospector} to - * match the path and extract variables. - * - *

- * It is important to understand that Spring MVC's matching is relative to the servlet - * path. This means if you have mapped any servlet to a path that starts with "/" and is - * greater than one, you should also specify the {@link #setServletPath(String)} attribute - * to differentiate mappings. - *

- * - * @author Rob Winch - * @author Eddú Meléndez - * @author Evgeniy Cheban - * @since 4.1.1 - * @deprecated Please use {@link PathPatternRequestMatcher} instead - */ -@Deprecated(forRemoval = true) -public class MvcRequestMatcher implements RequestMatcher, RequestVariablesExtractor { - - private final DefaultMatcher defaultMatcher = new DefaultMatcher(); - - private final HandlerMappingIntrospector introspector; - - private final String pattern; - - private HttpMethod method; - - private String servletPath; - - public MvcRequestMatcher(HandlerMappingIntrospector introspector, String pattern) { - this.introspector = introspector; - this.pattern = pattern; - } - - @Override - public boolean matches(HttpServletRequest request) { - if (notMatchMethodOrServletPath(request)) { - return false; - } - MatchableHandlerMapping mapping = getMapping(request); - if (mapping == null) { - return this.defaultMatcher.matches(request); - } - RequestMatchResult matchResult = mapping.match(request, this.pattern); - return matchResult != null; - } - - @Override - @Deprecated - public Map extractUriTemplateVariables(HttpServletRequest request) { - return matcher(request).getVariables(); - } - - @Override - public MatchResult matcher(HttpServletRequest request) { - if (notMatchMethodOrServletPath(request)) { - return MatchResult.notMatch(); - } - MatchableHandlerMapping mapping = getMapping(request); - if (mapping == null) { - return this.defaultMatcher.matcher(request); - } - RequestMatchResult result = mapping.match(request, this.pattern); - return (result != null) ? MatchResult.match(result.extractUriTemplateVariables()) : MatchResult.notMatch(); - } - - private boolean notMatchMethodOrServletPath(HttpServletRequest request) { - return this.method != null && !this.method.name().equals(request.getMethod()) - || this.servletPath != null && !this.servletPath.equals(request.getServletPath()); - } - - private MatchableHandlerMapping getMapping(HttpServletRequest request) { - try { - return this.introspector.getMatchableHandlerMapping(request); - } - catch (Throwable ex) { - return null; - } - } - - /** - * @param method the method to set - */ - public void setMethod(HttpMethod method) { - this.method = method; - } - - /** - * The servlet path to match on. The default is undefined which means any servlet - * path. - * @param servletPath the servletPath to set - */ - public void setServletPath(String servletPath) { - this.servletPath = servletPath; - } - - protected final String getServletPath() { - return this.servletPath; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MvcRequestMatcher that = (MvcRequestMatcher) o; - return Objects.equals(this.pattern, that.pattern) && Objects.equals(this.method, that.method) - && Objects.equals(this.servletPath, that.servletPath); - } - - @Override - public int hashCode() { - return Objects.hash(this.pattern, this.method, this.servletPath); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Mvc [pattern='").append(this.pattern).append("'"); - if (this.servletPath != null) { - sb.append(", servletPath='").append(this.servletPath).append("'"); - } - if (this.method != null) { - sb.append(", ").append(this.method); - } - sb.append("]"); - return sb.toString(); - } - - private class DefaultMatcher implements RequestMatcher { - - private final UrlPathHelper pathHelper = new UrlPathHelper(); - - private final PathMatcher pathMatcher = new AntPathMatcher(); - - @Override - public boolean matches(HttpServletRequest request) { - String lookupPath = this.pathHelper.getLookupPathForRequest(request); - return matches(lookupPath); - } - - private boolean matches(String lookupPath) { - return this.pathMatcher.match(MvcRequestMatcher.this.pattern, lookupPath); - } - - @Override - public MatchResult matcher(HttpServletRequest request) { - String lookupPath = this.pathHelper.getLookupPathForRequest(request); - if (matches(lookupPath)) { - Map variables = this.pathMatcher - .extractUriTemplateVariables(MvcRequestMatcher.this.pattern, lookupPath); - return MatchResult.match(variables); - } - return MatchResult.notMatch(); - } - - } - - /** - * A builder for {@link MvcRequestMatcher} - * - * @author Marcus Da Coregio - * @since 5.8 - */ - public static final class Builder { - - private final HandlerMappingIntrospector introspector; - - private String servletPath; - - /** - * Construct a new instance of this builder - */ - public Builder(HandlerMappingIntrospector introspector) { - this.introspector = introspector; - } - - /** - * Sets the servlet path to be used by the {@link MvcRequestMatcher} generated by - * this builder - * @param servletPath the servlet path to use - * @return the {@link Builder} for further configuration - */ - public Builder servletPath(String servletPath) { - this.servletPath = servletPath; - return this; - } - - /** - * Creates an {@link MvcRequestMatcher} that uses the provided pattern to match - * @param pattern the pattern used to match - * @return the generated {@link MvcRequestMatcher} - */ - public MvcRequestMatcher pattern(String pattern) { - return pattern(null, pattern); - } - - /** - * Creates an {@link MvcRequestMatcher} that uses the provided pattern and HTTP - * method to match - * @param method the {@link HttpMethod}, can be null - * @param pattern the patterns used to match - * @return the generated {@link MvcRequestMatcher} - */ - public MvcRequestMatcher pattern(HttpMethod method, String pattern) { - MvcRequestMatcher mvcRequestMatcher = new MvcRequestMatcher(this.introspector, pattern); - mvcRequestMatcher.setServletPath(this.servletPath); - mvcRequestMatcher.setMethod(method); - return mvcRequestMatcher; - } - - } - -} diff --git a/web/src/main/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcher.java b/web/src/main/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcher.java index 86cc860e0ff..1abe7d94c91 100644 --- a/web/src/main/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcher.java +++ b/web/src/main/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcher.java @@ -138,7 +138,7 @@ public boolean equals(Object o) { if (!(o instanceof PathPatternRequestMatcher that)) { return false; } - return Objects.equals(this.pattern, that.pattern); + return Objects.equals(this.pattern, that.pattern) && Objects.equals(this.method, that.method); } /** @@ -146,7 +146,7 @@ public boolean equals(Object o) { */ @Override public int hashCode() { - return Objects.hash(this.pattern); + return Objects.hash(this.pattern, this.method); } /** diff --git a/web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java b/web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java deleted file mode 100644 index 0df94264f67..00000000000 --- a/web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java +++ /dev/null @@ -1,330 +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.web.util.matcher; - -import java.util.Collections; -import java.util.Locale; -import java.util.Map; - -import jakarta.servlet.http.HttpServletRequest; - -import org.springframework.http.HttpMethod; -import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; -import org.springframework.web.util.UrlPathHelper; - -/** - * Matcher which compares a pre-defined ant-style pattern against the URL ( - * {@code servletPath + pathInfo}) of an {@code HttpServletRequest}. The query string of - * the URL is ignored and matching is case-insensitive or case-sensitive depending on the - * arguments passed into the constructor. - *

- * Using a pattern value of {@code /**} or {@code **} is treated as a universal match, - * which will match any request. Patterns which end with {@code /**} (and have no other - * wildcards) are optimized by using a substring match — a pattern of - * {@code /aaa/**} will match {@code /aaa}, {@code /aaa/} and any sub-directories, such as - * {@code /aaa/bbb/ccc}. - *

- *

- * For all other cases, Spring's {@link AntPathMatcher} is used to perform the match. See - * the Spring documentation for this class for comprehensive information on the syntax - * used. - *

- * - * @author Luke Taylor - * @author Rob Winch - * @author Eddú Meléndez - * @author Evgeniy Cheban - * @author Manuel Jordan - * @since 3.1 - * @see org.springframework.util.AntPathMatcher - * @deprecated please use {@link PathPatternRequestMatcher} instead - */ -@Deprecated(forRemoval = true) -public final class AntPathRequestMatcher implements RequestMatcher, RequestVariablesExtractor { - - private static final String MATCH_ALL = "/**"; - - private final Matcher matcher; - - private final String pattern; - - private final HttpMethod httpMethod; - - private final boolean caseSensitive; - - private final UrlPathHelper urlPathHelper; - - /** - * Creates a matcher with the specific pattern which will match all HTTP methods in a - * case-sensitive manner. - * @param pattern the ant pattern to use for matching - * @since 5.8 - */ - public static AntPathRequestMatcher antMatcher(String pattern) { - Assert.hasText(pattern, "pattern cannot be empty"); - return new AntPathRequestMatcher(pattern); - } - - /** - * Creates a matcher that will match all request with the supplied HTTP method in a - * case-sensitive manner. - * @param method the HTTP method. The {@code matches} method will return false if the - * incoming request doesn't have the same method. - * @since 5.8 - */ - public static AntPathRequestMatcher antMatcher(HttpMethod method) { - Assert.notNull(method, "method cannot be null"); - return new AntPathRequestMatcher(MATCH_ALL, method.name()); - } - - /** - * Creates a matcher with the supplied pattern and HTTP method in a case-sensitive - * manner. - * @param method the HTTP method. The {@code matches} method will return false if the - * incoming request doesn't have the same method. - * @param pattern the ant pattern to use for matching - * @since 5.8 - */ - public static AntPathRequestMatcher antMatcher(HttpMethod method, String pattern) { - Assert.notNull(method, "method cannot be null"); - Assert.hasText(pattern, "pattern cannot be empty"); - return new AntPathRequestMatcher(pattern, method.name()); - } - - /** - * Creates a matcher with the specific pattern which will match all HTTP methods in a - * case sensitive manner. - * @param pattern the ant pattern to use for matching - */ - public AntPathRequestMatcher(String pattern) { - this(pattern, null); - } - - /** - * Creates a matcher with the supplied pattern and HTTP method in a case sensitive - * manner. - * @param pattern the ant pattern to use for matching - * @param httpMethod the HTTP method. The {@code matches} method will return false if - * the incoming request doesn't have the same method. - */ - public AntPathRequestMatcher(String pattern, String httpMethod) { - this(pattern, httpMethod, true); - } - - /** - * Creates a matcher with the supplied pattern which will match the specified Http - * method - * @param pattern the ant pattern to use for matching - * @param httpMethod the HTTP method. The {@code matches} method will return false if - * the incoming request doesn't doesn't have the same method. - * @param caseSensitive true if the matcher should consider case, else false - */ - public AntPathRequestMatcher(String pattern, String httpMethod, boolean caseSensitive) { - this(pattern, httpMethod, caseSensitive, null); - } - - /** - * Creates a matcher with the supplied pattern which will match the specified Http - * method - * @param pattern the ant pattern to use for matching - * @param httpMethod the HTTP method. The {@code matches} method will return false if - * the incoming request doesn't have the same method. - * @param caseSensitive true if the matcher should consider case, else false - * @param urlPathHelper if non-null, will be used for extracting the path from the - * HttpServletRequest - */ - public AntPathRequestMatcher(String pattern, String httpMethod, boolean caseSensitive, - UrlPathHelper urlPathHelper) { - Assert.hasText(pattern, "Pattern cannot be null or empty"); - this.caseSensitive = caseSensitive; - if (pattern.equals(MATCH_ALL) || pattern.equals("**")) { - pattern = MATCH_ALL; - this.matcher = null; - } - else { - // If the pattern ends with {@code /**} and has no other wildcards or path - // variables, then optimize to a sub-path match - if (pattern.endsWith(MATCH_ALL) - && (pattern.indexOf('?') == -1 && pattern.indexOf('{') == -1 && pattern.indexOf('}') == -1) - && pattern.indexOf("*") == pattern.length() - 2) { - this.matcher = new SubpathMatcher(pattern.substring(0, pattern.length() - 3), caseSensitive); - } - else { - this.matcher = new SpringAntMatcher(pattern, caseSensitive); - } - } - this.pattern = pattern; - this.httpMethod = StringUtils.hasText(httpMethod) ? HttpMethod.valueOf(httpMethod) : null; - this.urlPathHelper = urlPathHelper; - } - - /** - * Returns true if the configured pattern (and HTTP-Method) match those of the - * supplied request. - * @param request the request to match against. The ant pattern will be matched - * against the {@code servletPath} + {@code pathInfo} of the request. - */ - @Override - public boolean matches(HttpServletRequest request) { - if (this.httpMethod != null && StringUtils.hasText(request.getMethod()) - && this.httpMethod != HttpMethod.valueOf(request.getMethod())) { - return false; - } - if (this.pattern.equals(MATCH_ALL)) { - return true; - } - String url = getRequestPath(request); - return this.matcher.matches(url); - } - - @Override - @Deprecated - public Map extractUriTemplateVariables(HttpServletRequest request) { - return matcher(request).getVariables(); - } - - @Override - public MatchResult matcher(HttpServletRequest request) { - if (!matches(request)) { - return MatchResult.notMatch(); - } - if (this.matcher == null) { - return MatchResult.match(); - } - String url = getRequestPath(request); - return MatchResult.match(this.matcher.extractUriTemplateVariables(url)); - } - - private String getRequestPath(HttpServletRequest request) { - if (this.urlPathHelper != null) { - return this.urlPathHelper.getPathWithinApplication(request); - } - String url = request.getServletPath(); - String pathInfo = request.getPathInfo(); - if (pathInfo != null) { - url = StringUtils.hasLength(url) ? url + pathInfo : pathInfo; - } - return url; - } - - public String getPattern() { - return this.pattern; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof AntPathRequestMatcher other)) { - return false; - } - return this.pattern.equals(other.pattern) && this.httpMethod == other.httpMethod - && this.caseSensitive == other.caseSensitive; - } - - @Override - public int hashCode() { - int result = (this.pattern != null) ? this.pattern.hashCode() : 0; - result = 31 * result + ((this.httpMethod != null) ? this.httpMethod.hashCode() : 0); - result = 31 * result + (this.caseSensitive ? 1231 : 1237); - return result; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Ant [pattern='").append(this.pattern).append("'"); - if (this.httpMethod != null) { - sb.append(", ").append(this.httpMethod); - } - sb.append("]"); - return sb.toString(); - } - - private interface Matcher { - - boolean matches(String path); - - Map extractUriTemplateVariables(String path); - - } - - private static final class SpringAntMatcher implements Matcher { - - private final AntPathMatcher antMatcher; - - private final String pattern; - - private SpringAntMatcher(String pattern, boolean caseSensitive) { - this.pattern = pattern; - this.antMatcher = createMatcher(caseSensitive); - } - - @Override - public boolean matches(String path) { - return this.antMatcher.match(this.pattern, path); - } - - @Override - public Map extractUriTemplateVariables(String path) { - return this.antMatcher.extractUriTemplateVariables(this.pattern, path); - } - - private static AntPathMatcher createMatcher(boolean caseSensitive) { - AntPathMatcher matcher = new AntPathMatcher(); - matcher.setTrimTokens(false); - matcher.setCaseSensitive(caseSensitive); - return matcher; - } - - } - - /** - * Optimized matcher for trailing wildcards - */ - private static final class SubpathMatcher implements Matcher { - - private final String subpath; - - private final int length; - - private final boolean caseSensitive; - - private SubpathMatcher(String subpath, boolean caseSensitive) { - Assert.isTrue(!subpath.contains("*"), "subpath cannot contain \"*\""); - this.subpath = caseSensitive ? subpath : subpath.toLowerCase(Locale.ROOT); - this.length = subpath.length(); - this.caseSensitive = caseSensitive; - } - - @Override - public boolean matches(String path) { - if (!this.caseSensitive) { - path = path.toLowerCase(Locale.ROOT); - } - return path.startsWith(this.subpath) && (path.length() == this.length || path.charAt(this.length) == '/'); - } - - @Override - public Map extractUriTemplateVariables(String path) { - return Collections.emptyMap(); - } - - } - -} diff --git a/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java b/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java index 2e8f7a552a6..a1b1a5300fa 100644 --- a/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java +++ b/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java @@ -64,6 +64,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * @author Luke Taylor @@ -96,8 +97,7 @@ public void setup() throws Exception { }).given(this.filter).doFilter(any(), any(), any()); this.fcp = new FilterChainProxy(new DefaultSecurityFilterChain(this.matcher, Arrays.asList(this.filter))); this.fcp.setFilterChainValidator(mock(FilterChainProxy.FilterChainValidator.class)); - this.request = new MockHttpServletRequest("GET", ""); - this.request.setServletPath("/path"); + this.request = get("/path").build(); this.response = new MockHttpServletResponse(); this.chain = mock(FilterChain.class); } diff --git a/web/src/test/java/org/springframework/security/web/FilterInvocationTests.java b/web/src/test/java/org/springframework/security/web/FilterInvocationTests.java index 5b6fc258ea8..58a6fd2f982 100644 --- a/web/src/test/java/org/springframework/security/web/FilterInvocationTests.java +++ b/web/src/test/java/org/springframework/security/web/FilterInvocationTests.java @@ -34,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link FilterInvocation}. @@ -45,14 +46,8 @@ public class FilterInvocationTests { @Test public void testGettersAndStringMethods() { - MockHttpServletRequest request = new MockHttpServletRequest(null, null); - request.setServletPath("/HelloWorld"); - request.setPathInfo("/some/more/segments.html"); - request.setServerName("localhost"); - request.setScheme("http"); - request.setServerPort(80); - request.setContextPath("/mycontext"); - request.setRequestURI("/mycontext/HelloWorld/some/more/segments.html"); + MockHttpServletRequest request = get().requestUri("/mycontext", "/HelloWorld", "/some/more/segments.html") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); FilterInvocation fi = new FilterInvocation(request, response, chain); @@ -62,7 +57,7 @@ public void testGettersAndStringMethods() { assertThat(fi.getHttpResponse()).isEqualTo(response); assertThat(fi.getChain()).isEqualTo(chain); assertThat(fi.getRequestUrl()).isEqualTo("/HelloWorld/some/more/segments.html"); - assertThat(fi.toString()).isEqualTo("filter invocation [/HelloWorld/some/more/segments.html]"); + assertThat(fi.toString()).isEqualTo("filter invocation [GET /HelloWorld/some/more/segments.html]"); assertThat(fi.getFullRequestUrl()).isEqualTo("http://localhost/mycontext/HelloWorld/some/more/segments.html"); } @@ -89,34 +84,23 @@ public void testRejectsNullServletResponse() { @Test public void testStringMethodsWithAQueryString() { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setQueryString("foo=bar"); - request.setServletPath("/HelloWorld"); - request.setServerName("localhost"); - request.setScheme("http"); - request.setServerPort(80); - request.setContextPath("/mycontext"); - request.setRequestURI("/mycontext/HelloWorld"); + MockHttpServletRequest request = get().requestUri("/mycontext", "/HelloWorld", null) + .queryString("foo=bar") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); assertThat(fi.getRequestUrl()).isEqualTo("/HelloWorld?foo=bar"); - assertThat(fi.toString()).isEqualTo("filter invocation [/HelloWorld?foo=bar]"); + assertThat(fi.toString()).isEqualTo("filter invocation [GET /HelloWorld?foo=bar]"); assertThat(fi.getFullRequestUrl()).isEqualTo("http://localhost/mycontext/HelloWorld?foo=bar"); } @Test public void testStringMethodsWithoutAnyQueryString() { - MockHttpServletRequest request = new MockHttpServletRequest(null, null); - request.setServletPath("/HelloWorld"); - request.setServerName("localhost"); - request.setScheme("http"); - request.setServerPort(80); - request.setContextPath("/mycontext"); - request.setRequestURI("/mycontext/HelloWorld"); + MockHttpServletRequest request = get().requestUri("/mycontext", "/HelloWorld", null).build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); assertThat(fi.getRequestUrl()).isEqualTo("/HelloWorld"); - assertThat(fi.toString()).isEqualTo("filter invocation [/HelloWorld]"); + assertThat(fi.toString()).isEqualTo("filter invocation [GET /HelloWorld]"); assertThat(fi.getFullRequestUrl()).isEqualTo("http://localhost/mycontext/HelloWorld"); } diff --git a/web/src/test/java/org/springframework/security/web/RequestMatcherRedirectFilterTests.java b/web/src/test/java/org/springframework/security/web/RequestMatcherRedirectFilterTests.java index 29c8d46abf8..b03e6d4b07e 100644 --- a/web/src/test/java/org/springframework/security/web/RequestMatcherRedirectFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/RequestMatcherRedirectFilterTests.java @@ -22,13 +22,14 @@ import org.springframework.http.HttpStatus; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link RequestMatcherRedirectFilter}. @@ -37,14 +38,14 @@ */ public class RequestMatcherRedirectFilterTests { + private final PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults(); + @Test public void doFilterWhenRequestMatchThenRedirectToSpecifiedUrl() throws Exception { - RequestMatcherRedirectFilter filter = new RequestMatcherRedirectFilter(new AntPathRequestMatcher("/context"), + RequestMatcherRedirectFilter filter = new RequestMatcherRedirectFilter(this.builder.matcher("/context"), "/test"); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/context"); - + MockHttpServletRequest request = get("/context").build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); @@ -58,11 +59,10 @@ public void doFilterWhenRequestMatchThenRedirectToSpecifiedUrl() throws Exceptio @Test public void doFilterWhenRequestNotMatchThenNextFilter() throws Exception { - RequestMatcherRedirectFilter filter = new RequestMatcherRedirectFilter(new AntPathRequestMatcher("/context"), + RequestMatcherRedirectFilter filter = new RequestMatcherRedirectFilter(this.builder.matcher("/context"), "/test"); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/test"); + MockHttpServletRequest request = get("/test").build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); @@ -83,21 +83,21 @@ public void constructWhenRequestMatcherNull() { @Test public void constructWhenRedirectUrlNull() { assertThatIllegalArgumentException() - .isThrownBy(() -> new RequestMatcherRedirectFilter(new AntPathRequestMatcher("/**"), null)) + .isThrownBy(() -> new RequestMatcherRedirectFilter(this.builder.matcher("/**"), null)) .withMessage("redirectUrl cannot be empty"); } @Test public void constructWhenRedirectUrlEmpty() { assertThatIllegalArgumentException() - .isThrownBy(() -> new RequestMatcherRedirectFilter(new AntPathRequestMatcher("/**"), "")) + .isThrownBy(() -> new RequestMatcherRedirectFilter(this.builder.matcher("/**"), "")) .withMessage("redirectUrl cannot be empty"); } @Test public void constructWhenRedirectUrlBlank() { assertThatIllegalArgumentException() - .isThrownBy(() -> new RequestMatcherRedirectFilter(new AntPathRequestMatcher("/**"), " ")) + .isThrownBy(() -> new RequestMatcherRedirectFilter(this.builder.matcher("/**"), " ")) .withMessage("redirectUrl cannot be empty"); } diff --git a/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java b/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java index 89159fd7377..11fe3e41d2e 100644 --- a/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/access/ExceptionTranslationFilterTests.java @@ -58,6 +58,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link ExceptionTranslationFilter}. @@ -86,13 +87,7 @@ private static String getSavedRequestUrl(HttpServletRequest request) { @Test public void testAccessDeniedWhenAnonymous() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); - request.setServerPort(80); - request.setScheme("http"); - request.setServerName("localhost"); - request.setContextPath("/mycontext"); - request.setRequestURI("/mycontext/secure/page.html"); + MockHttpServletRequest request = get().requestUri("/mycontext", "/secure/page.html", null).build(); // Setup the FilterChain to thrown an access denied exception FilterChain fc = mockFilterChainWithException(new AccessDeniedException("")); // Setup SecurityContextHolder, as filter needs to check if user is @@ -129,13 +124,7 @@ public void testAccessDeniedWhenAnonymousThenIncludesAuthenticationRequest() thr @Test public void testAccessDeniedWithRememberMe() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); - request.setServerPort(80); - request.setScheme("http"); - request.setServerName("localhost"); - request.setContextPath("/mycontext"); - request.setRequestURI("/mycontext/secure/page.html"); + MockHttpServletRequest request = get().requestUri("/mycontext", "/secure/page.html", null).build(); // Setup the FilterChain to thrown an access denied exception FilterChain fc = mockFilterChainWithException(new AccessDeniedException("")); // Setup SecurityContextHolder, as filter needs to check if user is remembered @@ -155,8 +144,7 @@ public void testAccessDeniedWithRememberMe() throws Exception { @Test public void testAccessDeniedWhenNonAnonymous() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); + MockHttpServletRequest request = get("/secure/page.html").build(); // Setup the FilterChain to thrown an access denied exception FilterChain fc = mockFilterChainWithException(new AccessDeniedException("")); // Setup SecurityContextHolder, as filter needs to check if user is @@ -178,8 +166,7 @@ public void testAccessDeniedWhenNonAnonymous() throws Exception { @Test public void testLocalizedErrorMessages() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); + MockHttpServletRequest request = get("/secure/page.html").build(); // Setup the FilterChain to thrown an access denied exception FilterChain fc = mockFilterChainWithException(new AccessDeniedException("")); // Setup SecurityContextHolder, as filter needs to check if user is @@ -202,13 +189,7 @@ public void testLocalizedErrorMessages() throws Exception { @Test public void redirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); - request.setServerPort(80); - request.setScheme("http"); - request.setServerName("localhost"); - request.setContextPath("/mycontext"); - request.setRequestURI("/mycontext/secure/page.html"); + MockHttpServletRequest request = get().requestUri("/mycontext", "/secure/page.html", null).build(); // Setup the FilterChain to thrown an authentication failure exception FilterChain fc = mockFilterChainWithException(new BadCredentialsException("")); // Test @@ -225,13 +206,9 @@ public void redirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthentication public void redirectedToLoginFormAndSessionShowsOriginalTargetWithExoticPortWhenAuthenticationException() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); - request.setServerPort(8080); - request.setScheme("http"); - request.setServerName("localhost"); - request.setContextPath("/mycontext"); - request.setRequestURI("/mycontext/secure/page.html"); + MockHttpServletRequest request = get("http://localhost:8080") + .requestUri("/mycontext", "/secure/page.html", null) + .build(); // Setup the FilterChain to thrown an authentication failure exception FilterChain fc = mockFilterChainWithException(new BadCredentialsException("")); // Test @@ -258,8 +235,7 @@ public void startupDetectsMissingRequestCache() { @Test public void successfulAccessGrant() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); + MockHttpServletRequest request = get("/secure/page.html").build(); // Test ExceptionTranslationFilter filter = new ExceptionTranslationFilter(this.mockEntryPoint); assertThat(filter.getAuthenticationEntryPoint()).isSameAs(this.mockEntryPoint); diff --git a/web/src/test/java/org/springframework/security/web/access/HandlerMappingIntrospectorRequestTransformerTests.java b/web/src/test/java/org/springframework/security/web/access/HandlerMappingIntrospectorRequestTransformerTests.java deleted file mode 100644 index 96bf8e95814..00000000000 --- a/web/src/test/java/org/springframework/security/web/access/HandlerMappingIntrospectorRequestTransformerTests.java +++ /dev/null @@ -1,206 +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.web.access; - -import java.util.Collections; - -import jakarta.servlet.DispatcherType; -import jakarta.servlet.http.HttpServletRequest; -import org.assertj.core.api.AssertionsForClassTypes; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -/** - * @author Rob Winch - */ -@ExtendWith(MockitoExtension.class) -class HandlerMappingIntrospectorRequestTransformerTests { - - @Mock - HandlerMappingIntrospector hmi; - - HandlerMappingIntrospectorRequestTransformer transformer; - - @BeforeEach - void setup() { - this.transformer = new HandlerMappingIntrospectorRequestTransformer(this.hmi); - } - - @Test - void constructorWhenHmiIsNullThenIllegalArgumentException() { - AssertionsForClassTypes.assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> new HandlerMappingIntrospectorRequestTransformer(null)); - } - - @Test - void transformThenNewRequestPassedToSetCache() { - MockHttpServletRequest request = new MockHttpServletRequest(); - - HttpServletRequest transformedRequest = this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - assertThat(transformedRequest).isNotEqualTo(request); - } - - @Test - void transformThenResultPassedToSetCache() { - MockHttpServletRequest request = new MockHttpServletRequest(); - - HttpServletRequest transformedRequest = this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - assertThat(requestArg.getValue()).isEqualTo(transformedRequest); - } - - /** - * The request passed into the transformer does not allow interactions on certain - * methods, we need to ensure that the methods used by - * {@link HandlerMappingIntrospector#setCache(HttpServletRequest)} are overridden. - */ - @Test - void transformThenResultDoesNotDelegateToSetAttribute() { - HttpServletRequest request = mock(HttpServletRequest.class); - - this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - HttpServletRequest transformedRequest = requestArg.getValue(); - String attrName = "any"; - String attrValue = "value"; - transformedRequest.setAttribute(attrName, attrValue); - verifyNoInteractions(request); - assertThat(transformedRequest.getAttribute(attrName)).isEqualTo(attrValue); - } - - @Test - void transformThenSetAttributeWorks() { - HttpServletRequest request = mock(HttpServletRequest.class); - - this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - HttpServletRequest transformedRequest = requestArg.getValue(); - String attrName = "any"; - String attrValue = "value"; - transformedRequest.setAttribute(attrName, attrValue); - assertThat(transformedRequest.getAttribute(attrName)).isEqualTo(attrValue); - } - - /** - * The request passed into the transformer does not allow interactions on certain - * methods, we need to ensure that the methods used by - * {@link HandlerMappingIntrospector#setCache(HttpServletRequest)} are overridden. - */ - @Test - void transformThenResultDoesNotDelegateToGetAttribute() { - HttpServletRequest request = mock(HttpServletRequest.class); - - this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - HttpServletRequest transformedRequest = requestArg.getValue(); - transformedRequest.getAttribute("any"); - verifyNoInteractions(request); - } - - /** - * The request passed into the transformer does not allow interactions on certain - * methods, we need to ensure that the methods used by - * {@link HandlerMappingIntrospector#setCache(HttpServletRequest)} are overridden. - */ - @Test - void transformThenResultDoesNotDelegateToGetAttributeNames() { - HttpServletRequest request = mock(HttpServletRequest.class); - - this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - HttpServletRequest transformedRequest = requestArg.getValue(); - transformedRequest.getAttributeNames(); - verifyNoInteractions(request); - } - - @Test - void transformThenGetAttributeNamesWorks() { - HttpServletRequest request = mock(HttpServletRequest.class); - - this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - HttpServletRequest transformedRequest = requestArg.getValue(); - String attrName = "any"; - String attrValue = "value"; - transformedRequest.setAttribute(attrName, attrValue); - assertThat(Collections.list(transformedRequest.getAttributeNames())).containsExactly(attrName); - } - - /** - * The request passed into the transformer does not allow interactions on certain - * methods, we need to ensure that the methods used by - * {@link HandlerMappingIntrospector#setCache(HttpServletRequest)} are overridden. - */ - @Test - void transformThenResultDoesNotDelegateToRemoveAttribute() { - HttpServletRequest request = mock(HttpServletRequest.class); - - this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - HttpServletRequest transformedRequest = requestArg.getValue(); - transformedRequest.removeAttribute("any"); - verifyNoInteractions(request); - } - - /** - * The request passed into the transformer does not allow interactions on certain - * methods, we need to ensure that the methods used by - * {@link HandlerMappingIntrospector#setCache(HttpServletRequest)} are overridden. - */ - @Test - void transformThenResultDoesNotDelegateToGetDispatcherType() { - HttpServletRequest request = mock(HttpServletRequest.class); - - this.transformer.transform(request); - - ArgumentCaptor requestArg = ArgumentCaptor.forClass(HttpServletRequest.class); - verify(this.hmi).setCache(requestArg.capture()); - HttpServletRequest transformedRequest = requestArg.getValue(); - assertThat(transformedRequest.getDispatcherType()).isEqualTo(DispatcherType.REQUEST); - verifyNoInteractions(request); - } - -} diff --git a/web/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java b/web/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java index 348b3b2152a..ad3f3afa664 100644 --- a/web/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/access/channel/ChannelProcessingFilterTests.java @@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link ChannelProcessingFilter}. @@ -81,9 +82,8 @@ public void testDoFilterWhenManagerDoesCommitResponse() throws Exception { filter.setChannelDecisionManager(new MockChannelDecisionManager(true, "SOME_ATTRIBUTE")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE"); filter.setSecurityMetadataSource(fids); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/path").build(); request.setQueryString("info=now"); - request.setServletPath("/path"); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, mock(FilterChain.class)); } @@ -94,9 +94,8 @@ public void testDoFilterWhenManagerDoesNotCommitResponse() throws Exception { filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "SOME_ATTRIBUTE")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE"); filter.setSecurityMetadataSource(fids); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/path").build(); request.setQueryString("info=now"); - request.setServletPath("/path"); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, mock(FilterChain.class)); } @@ -107,9 +106,8 @@ public void testDoFilterWhenNullConfigAttributeReturned() throws Exception { filter.setChannelDecisionManager(new MockChannelDecisionManager(false, "NOT_USED")); MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "NOT_USED"); filter.setSecurityMetadataSource(fids); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE").build(); request.setQueryString("info=now"); - request.setServletPath("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE"); MockHttpServletResponse response = new MockHttpServletResponse(); filter.doFilter(request, response, mock(FilterChain.class)); } diff --git a/web/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java b/web/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java index 1a3f8f14800..1c290cac060 100644 --- a/web/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java +++ b/web/src/test/java/org/springframework/security/web/access/channel/InsecureChannelProcessorTests.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link InsecureChannelProcessor}. @@ -37,13 +38,9 @@ public class InsecureChannelProcessorTests { @Test public void testDecideDetectsAcceptableChannel() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setQueryString("info=true"); - request.setServerName("localhost"); - request.setContextPath("/bigapp"); - request.setServletPath("/servlet"); - request.setScheme("http"); - request.setServerPort(8080); + MockHttpServletRequest request = get("http://localhost:8080").requestUri("/bigapp", "/servlet", null) + .queryString("info=true") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); InsecureChannelProcessor processor = new InsecureChannelProcessor(); @@ -53,14 +50,9 @@ public void testDecideDetectsAcceptableChannel() throws Exception { @Test public void testDecideDetectsUnacceptableChannel() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setQueryString("info=true"); - request.setServerName("localhost"); - request.setContextPath("/bigapp"); - request.setServletPath("/servlet"); - request.setScheme("https"); - request.setSecure(true); - request.setServerPort(8443); + MockHttpServletRequest request = get("https://localhost:8443").requestUri("/bigapp", "/servlet", null) + .queryString("info=true") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); InsecureChannelProcessor processor = new InsecureChannelProcessor(); diff --git a/web/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java b/web/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java index 005736b336d..4263cec2333 100644 --- a/web/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java +++ b/web/src/test/java/org/springframework/security/web/access/channel/SecureChannelProcessorTests.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link SecureChannelProcessor}. @@ -37,14 +38,9 @@ public class SecureChannelProcessorTests { @Test public void testDecideDetectsAcceptableChannel() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setQueryString("info=true"); - request.setServerName("localhost"); - request.setContextPath("/bigapp"); - request.setServletPath("/servlet"); - request.setScheme("https"); - request.setSecure(true); - request.setServerPort(8443); + MockHttpServletRequest request = get("https://localhost:8443").requestUri("/bigapp", "/servlet", null) + .queryString("info=true") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); SecureChannelProcessor processor = new SecureChannelProcessor(); @@ -54,13 +50,9 @@ public void testDecideDetectsAcceptableChannel() throws Exception { @Test public void testDecideDetectsUnacceptableChannel() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setQueryString("info=true"); - request.setServerName("localhost"); - request.setContextPath("/bigapp"); - request.setServletPath("/servlet"); - request.setScheme("http"); - request.setServerPort(8080); + MockHttpServletRequest request = get("http://localhost:8080").requestUri("/bigapp", "/servlet", null) + .queryString("info=true") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); FilterInvocation fi = new FilterInvocation(request, response, mock(FilterChain.class)); SecureChannelProcessor processor = new SecureChannelProcessor(); diff --git a/web/src/test/java/org/springframework/security/web/access/expression/AbstractVariableEvaluationContextPostProcessorTests.java b/web/src/test/java/org/springframework/security/web/access/expression/AbstractVariableEvaluationContextPostProcessorTests.java index d9bb23e6a28..aec21451367 100644 --- a/web/src/test/java/org/springframework/security/web/access/expression/AbstractVariableEvaluationContextPostProcessorTests.java +++ b/web/src/test/java/org/springframework/security/web/access/expression/AbstractVariableEvaluationContextPostProcessorTests.java @@ -31,6 +31,7 @@ import org.springframework.security.web.FilterInvocation; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * @author Rob Winch @@ -54,8 +55,7 @@ public class AbstractVariableEvaluationContextPostProcessorTests { @BeforeEach public void setup() { this.processor = new VariableEvaluationContextPostProcessor(); - this.request = new MockHttpServletRequest(); - this.request.setServletPath("/"); + this.request = get("/").build(); this.response = new MockHttpServletResponse(); this.invocation = new FilterInvocation(this.request, this.response, new MockFilterChain()); this.context = new StandardEvaluationContext(); diff --git a/web/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java b/web/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java index 8a111bd3579..1e9fac9ebeb 100644 --- a/web/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java +++ b/web/src/test/java/org/springframework/security/web/access/intercept/DefaultFilterInvocationSecurityMetadataSourceTests.java @@ -22,16 +22,18 @@ import jakarta.servlet.FilterChain; import org.junit.jupiter.api.Test; +import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; -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; import static org.mockito.Mockito.mock; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.request; /** * Tests {@link DefaultFilterInvocationSecurityMetadataSource}. @@ -44,9 +46,9 @@ public class DefaultFilterInvocationSecurityMetadataSourceTests { private Collection def = SecurityConfig.createList("ROLE_ONE"); - private void createFids(String pattern, String method) { + private void createFids(String pattern, HttpMethod method) { LinkedHashMap> requestMap = new LinkedHashMap<>(); - requestMap.put(new AntPathRequestMatcher(pattern, method), this.def); + requestMap.put(PathPatternRequestMatcher.withDefaults().matcher(method, pattern), this.def); this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap); } @@ -88,7 +90,7 @@ public void lookupRequiringExactMatchWithAdditionalSlashesIsSuccessful() { @Test public void httpMethodLookupSucceeds() { - createFids("/somepage**", "GET"); + createFids("/somepage**", HttpMethod.GET); FilterInvocation fi = createFilterInvocation("/somepage", null, null, "GET"); Collection attrs = this.fids.getAttributes(fi); assertThat(attrs).isEqualTo(this.def); @@ -104,7 +106,7 @@ public void generalMatchIsUsedIfNoMethodSpecificMatchExists() { @Test public void requestWithDifferentHttpMethodDoesntMatch() { - createFids("/somepage**", "GET"); + createFids("/somepage**", HttpMethod.GET); FilterInvocation fi = createFilterInvocation("/somepage", null, null, "POST"); Collection attrs = this.fids.getAttributes(fi); assertThat(attrs).isNull(); @@ -115,8 +117,9 @@ public void requestWithDifferentHttpMethodDoesntMatch() { public void mixingPatternsWithAndWithoutHttpMethodsIsSupported() { LinkedHashMap> requestMap = new LinkedHashMap<>(); Collection userAttrs = SecurityConfig.createList("A"); - requestMap.put(new AntPathRequestMatcher("/user/**", null), userAttrs); - requestMap.put(new AntPathRequestMatcher("/teller/**", "GET"), SecurityConfig.createList("B")); + requestMap.put(PathPatternRequestMatcher.withDefaults().matcher("/user/**"), userAttrs); + requestMap.put(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/teller/**"), + SecurityConfig.createList("B")); this.fids = new DefaultFilterInvocationSecurityMetadataSource(requestMap); FilterInvocation fi = createFilterInvocation("/user", null, null, "GET"); Collection attrs = this.fids.getAttributes(fi); @@ -139,12 +142,9 @@ public void extraQuestionMarkStillMatches() { private FilterInvocation createFilterInvocation(String servletPath, String pathInfo, String queryString, String method) { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI(null); - request.setMethod(method); - request.setServletPath(servletPath); - request.setPathInfo(pathInfo); - request.setQueryString(queryString); + MockHttpServletRequest request = request(method).requestUri(null, servletPath, pathInfo) + .queryString(queryString) + .build(); return new FilterInvocation(request, new MockHttpServletResponse(), mock(FilterChain.class)); } diff --git a/web/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java b/web/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java index 4408b14147a..77370b0cd73 100644 --- a/web/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java +++ b/web/src/test/java/org/springframework/security/web/access/intercept/FilterSecurityInterceptorTests.java @@ -53,6 +53,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link FilterSecurityInterceptor}. @@ -188,8 +189,7 @@ public void doFilterWhenObserveOncePerRequestFalseAndInvokedTwiceThenObserveTwic private FilterInvocation createinvocation() { MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure/page.html"); + MockHttpServletRequest request = get("/secure/page.html").build(); FilterChain chain = mock(FilterChain.class); FilterInvocation fi = new FilterInvocation(request, response, chain); return fi; diff --git a/web/src/test/java/org/springframework/security/web/access/intercept/RequestMatcherDelegatingAuthorizationManagerTests.java b/web/src/test/java/org/springframework/security/web/access/intercept/RequestMatcherDelegatingAuthorizationManagerTests.java index dfb754fed56..e360379c072 100644 --- a/web/src/test/java/org/springframework/security/web/access/intercept/RequestMatcherDelegatingAuthorizationManagerTests.java +++ b/web/src/test/java/org/springframework/security/web/access/intercept/RequestMatcherDelegatingAuthorizationManagerTests.java @@ -28,8 +28,7 @@ import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.SingleResultAuthorizationManager; import org.springframework.security.core.Authentication; -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.RequestMatcherEntry; @@ -45,6 +44,8 @@ */ public class RequestMatcherDelegatingAuthorizationManagerTests { + private final PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults(); + @Test public void buildWhenMappingsEmptyThenException() { assertThatIllegalArgumentException() @@ -65,7 +66,7 @@ public void addWhenMatcherNullThenException() { public void addWhenManagerNullThenException() { assertThatIllegalArgumentException() .isThrownBy(() -> RequestMatcherDelegatingAuthorizationManager.builder() - .add(new MvcRequestMatcher(null, "/grant"), null) + .add(this.builder.matcher("/grant"), null) .build()) .withMessage("manager cannot be null"); } @@ -73,8 +74,8 @@ public void addWhenManagerNullThenException() { @Test public void checkWhenMultipleMappingsConfiguredThenDelegatesMatchingManager() { RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder() - .add(new MvcRequestMatcher(null, "/grant"), SingleResultAuthorizationManager.permitAll()) - .add(new MvcRequestMatcher(null, "/deny"), SingleResultAuthorizationManager.denyAll()) + .add(this.builder.matcher(null, "/grant"), SingleResultAuthorizationManager.permitAll()) + .add(this.builder.matcher(null, "/deny"), SingleResultAuthorizationManager.denyAll()) .build(); Supplier authentication = () -> new TestingAuthenticationToken("user", "password", "ROLE_USER"); @@ -97,11 +98,11 @@ public void checkWhenMultipleMappingsConfiguredThenDelegatesMatchingManager() { public void checkWhenMultipleMappingsConfiguredWithConsumerThenDelegatesMatchingManager() { RequestMatcherDelegatingAuthorizationManager manager = RequestMatcherDelegatingAuthorizationManager.builder() .mappings((m) -> { - m.add(new RequestMatcherEntry<>(new MvcRequestMatcher(null, "/grant"), + m.add(new RequestMatcherEntry<>(this.builder.matcher("/grant"), SingleResultAuthorizationManager.permitAll())); m.add(new RequestMatcherEntry<>(AnyRequestMatcher.INSTANCE, AuthorityAuthorizationManager.hasRole("ADMIN"))); - m.add(new RequestMatcherEntry<>(new MvcRequestMatcher(null, "/afterAny"), + m.add(new RequestMatcherEntry<>(this.builder.matcher("/afterAny"), SingleResultAuthorizationManager.permitAll())); }) .build(); @@ -156,7 +157,7 @@ public void requestMatchersWhenConfiguredAfterAnyRequestThenException() { .isThrownBy(() -> RequestMatcherDelegatingAuthorizationManager.builder() .anyRequest() .authenticated() - .requestMatchers(new AntPathRequestMatcher("/authenticated")) + .requestMatchers(this.builder.matcher("/authenticated")) .authenticated() .build()) .withMessage("Can't configure requestMatchers after anyRequest"); diff --git a/web/src/test/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilterTests.java index 00e4de0614c..1ba9b341872 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilterTests.java @@ -47,7 +47,7 @@ import org.springframework.security.web.context.RequestAttributeSecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.firewall.DefaultHttpFirewall; -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; @@ -59,6 +59,9 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.Builder; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * Tests {@link AbstractAuthenticationProcessingFilter}. @@ -75,13 +78,11 @@ public class AbstractAuthenticationProcessingFilterTests { SimpleUrlAuthenticationFailureHandler failureHandler; private MockHttpServletRequest createMockAuthenticationRequest() { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/j_mock_post"); - request.setScheme("http"); - request.setServerName("www.example.com"); - request.setRequestURI("/mycontext/j_mock_post"); - request.setContextPath("/mycontext"); - return request; + return withMockAuthenticationRequest().build(); + } + + private Builder withMockAuthenticationRequest() { + return get("www.example.com").requestUri("/mycontext", "/j_mock_post", null); } @BeforeEach @@ -100,12 +101,11 @@ public void tearDown() { @Test public void testDefaultProcessesFilterUrlMatchesWithPathParameter() { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login;jsessionid=I8MIONOSTHOR"); + MockHttpServletRequest request = post("/login;jsessionid=I8MIONOSTHOR").build(); MockHttpServletResponse response = new MockHttpServletResponse(); MockAuthenticationFilter filter = new MockAuthenticationFilter(); filter.setFilterProcessesUrl("/login"); DefaultHttpFirewall firewall = new DefaultHttpFirewall(); - request.setServletPath("/login;jsessionid=I8MIONOSTHOR"); // the firewall ensures that path parameters are ignored HttpServletRequest firewallRequest = firewall.getFirewalledRequest(request); assertThat(filter.requiresAuthentication(firewallRequest, response)).isTrue(); @@ -114,9 +114,9 @@ public void testDefaultProcessesFilterUrlMatchesWithPathParameter() { @Test public void testFilterProcessesUrlVariationsRespected() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = createMockAuthenticationRequest(); - request.setServletPath("/j_OTHER_LOCATION"); - request.setRequestURI("/mycontext/j_OTHER_LOCATION"); + MockHttpServletRequest request = withMockAuthenticationRequest() + .requestUri("/mycontext", "/j_OTHER_LOCATION", null) + .build(); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will not be invoked, as we redirect @@ -150,9 +150,9 @@ public void testGettersSetters() { @Test public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = createMockAuthenticationRequest(); - request.setServletPath("/some.file.html"); - request.setRequestURI("/mycontext/some.file.html"); + MockHttpServletRequest request = withMockAuthenticationRequest() + .requestUri("/mycontext", "/some.file.html", null) + .build(); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); // Setup our expectation that the filter chain will be invoked, as our request is @@ -227,9 +227,9 @@ public void testNormalOperationWithDefaultFilterProcessesUrlAndAuthenticationMan @Test public void testNormalOperationWithRequestMatcherAndAuthenticationManager() throws Exception { // Setup our HTTP request - MockHttpServletRequest request = createMockAuthenticationRequest(); - request.setServletPath("/j_eradicate_corona_virus"); - request.setRequestURI("/mycontext/j_eradicate_corona_virus"); + MockHttpServletRequest request = withMockAuthenticationRequest() + .requestUri("/mycontext", "/j_eradicate_corona_virus", null) + .build(); HttpSession sessionPreAuth = request.getSession(); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(null, null); @@ -239,7 +239,8 @@ public void testNormalOperationWithRequestMatcherAndAuthenticationManager() thro MockHttpServletResponse response = new MockHttpServletResponse(); // Setup our test object, to grant access MockAuthenticationFilter filter = new MockAuthenticationFilter( - new AntPathRequestMatcher("/j_eradicate_corona_virus"), mock(AuthenticationManager.class)); + PathPatternRequestMatcher.withDefaults().matcher("/j_eradicate_corona_virus"), + mock(AuthenticationManager.class)); filter.setSessionAuthenticationStrategy(mock(SessionAuthenticationStrategy.class)); filter.setAuthenticationSuccessHandler(this.successHandler); filter.setAuthenticationFailureHandler(this.failureHandler); @@ -273,7 +274,7 @@ public void testStartupDetectsInvalidFilterProcessesUrl() { filter.setAuthenticationManager(mock(AuthenticationManager.class)); filter.setAuthenticationSuccessHandler(this.successHandler); assertThatIllegalArgumentException().isThrownBy(() -> filter.setFilterProcessesUrl(null)) - .withMessage("Pattern cannot be null or empty"); + .withMessage("pattern cannot be null"); } @Test diff --git a/web/src/test/java/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPointTests.java b/web/src/test/java/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPointTests.java index 91e2d93cdfa..a1483034c0f 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPointTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/LoginUrlAuthenticationEntryPointTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link LoginUrlAuthenticationEntryPoint}. @@ -73,12 +74,7 @@ public void testGettersSetters() { @Test public void testHttpsOperationFromOriginalHttpUrl() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI("/some_path"); - request.setScheme("http"); - request.setServerName("www.example.com"); - request.setContextPath("/bigWebApp"); - request.setServerPort(80); + MockHttpServletRequest request = get("http://127.0.0.1").requestUri("/bigWebApp", "/some_path", null).build(); MockHttpServletResponse response = new MockHttpServletResponse(); LoginUrlAuthenticationEntryPoint ep = new LoginUrlAuthenticationEntryPoint("/hello"); ep.setPortMapper(new PortMapperImpl()); @@ -87,17 +83,17 @@ public void testHttpsOperationFromOriginalHttpUrl() throws Exception { ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); ep.commence(request, response, null); - assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com/bigWebApp/hello"); + assertThat(response.getRedirectedUrl()).isEqualTo("https://127.0.0.1/bigWebApp/hello"); request.setServerPort(8080); response = new MockHttpServletResponse(); ep.setPortResolver(new MockPortResolver(8080, 8443)); ep.commence(request, response, null); - assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com:8443/bigWebApp/hello"); + assertThat(response.getRedirectedUrl()).isEqualTo("https://127.0.0.1:8443/bigWebApp/hello"); // Now test an unusual custom HTTP:HTTPS is handled properly request.setServerPort(8888); response = new MockHttpServletResponse(); ep.commence(request, response, null); - assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com:8443/bigWebApp/hello"); + assertThat(response.getRedirectedUrl()).isEqualTo("https://127.0.0.1:8443/bigWebApp/hello"); PortMapperImpl portMapper = new PortMapperImpl(); Map map = new HashMap<>(); map.put("8888", "9999"); @@ -110,17 +106,13 @@ public void testHttpsOperationFromOriginalHttpUrl() throws Exception { ep.setPortResolver(new MockPortResolver(8888, 9999)); ep.afterPropertiesSet(); ep.commence(request, response, null); - assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com:9999/bigWebApp/hello"); + assertThat(response.getRedirectedUrl()).isEqualTo("https://127.0.0.1:9999/bigWebApp/hello"); } @Test public void testHttpsOperationFromOriginalHttpsUrl() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI("/some_path"); - request.setScheme("https"); - request.setServerName("www.example.com"); - request.setContextPath("/bigWebApp"); - request.setServerPort(443); + MockHttpServletRequest request = get("https://www.example.com:443").requestUri("/bigWebApp", "/some_path", null) + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); LoginUrlAuthenticationEntryPoint ep = new LoginUrlAuthenticationEntryPoint("/hello"); ep.setPortMapper(new PortMapperImpl()); @@ -149,13 +141,7 @@ public void testNormalOperation() throws Exception { ep.setPortMapper(new PortMapperImpl()); ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI("/some_path"); - request.setContextPath("/bigWebApp"); - request.setScheme("http"); - request.setServerName("localhost"); - request.setContextPath("/bigWebApp"); - request.setServerPort(80); + MockHttpServletRequest request = get().requestUri("/bigWebApp", "/some_path", null).build(); MockHttpServletResponse response = new MockHttpServletResponse(); ep.commence(request, response, null); assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost/bigWebApp/hello"); @@ -167,13 +153,8 @@ public void testOperationWhenHttpsRequestsButHttpsPortUnknown() throws Exception ep.setPortResolver(new MockPortResolver(8888, 1234)); ep.setForceHttps(true); ep.afterPropertiesSet(); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI("/some_path"); - request.setContextPath("/bigWebApp"); - request.setScheme("http"); - request.setServerName("localhost"); - request.setContextPath("/bigWebApp"); - request.setServerPort(8888); // NB: Port we can't resolve + MockHttpServletRequest request = get("http://localhost:8888").requestUri("/bigWebApp", "/some_path", null) + .build(); // NB: Port we can't resolve MockHttpServletResponse response = new MockHttpServletResponse(); ep.commence(request, response, null); // Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to HTTP port @@ -186,14 +167,7 @@ public void testServerSideRedirectWithoutForceHttpsForwardsToLoginPage() throws LoginUrlAuthenticationEntryPoint ep = new LoginUrlAuthenticationEntryPoint("/hello"); ep.setUseForward(true); ep.afterPropertiesSet(); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI("/bigWebApp/some_path"); - request.setServletPath("/some_path"); - request.setContextPath("/bigWebApp"); - request.setScheme("http"); - request.setServerName("www.example.com"); - request.setContextPath("/bigWebApp"); - request.setServerPort(80); + MockHttpServletRequest request = get().requestUri("/bigWebApp", "/some_path", null).build(); MockHttpServletResponse response = new MockHttpServletResponse(); ep.commence(request, response, null); assertThat(response.getForwardedUrl()).isEqualTo("/hello"); @@ -205,17 +179,10 @@ public void testServerSideRedirectWithForceHttpsRedirectsCurrentRequest() throws ep.setUseForward(true); ep.setForceHttps(true); ep.afterPropertiesSet(); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRequestURI("/bigWebApp/some_path"); - request.setServletPath("/some_path"); - request.setContextPath("/bigWebApp"); - request.setScheme("http"); - request.setServerName("www.example.com"); - request.setContextPath("/bigWebApp"); - request.setServerPort(80); + MockHttpServletRequest request = get("http://127.0.0.1").requestUri("/bigWebApp", "/some_path", null).build(); MockHttpServletResponse response = new MockHttpServletResponse(); ep.commence(request, response, null); - assertThat(response.getRedirectedUrl()).isEqualTo("https://www.example.com/bigWebApp/some_path"); + assertThat(response.getRedirectedUrl()).isEqualTo("https://127.0.0.1/bigWebApp/some_path"); } // SEC-1498 diff --git a/web/src/test/java/org/springframework/security/web/authentication/RequestMatcherDelegatingAuthenticationManagerResolverTests.java b/web/src/test/java/org/springframework/security/web/authentication/RequestMatcherDelegatingAuthenticationManagerResolverTests.java index de9e3e2561e..3362b108e9d 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/RequestMatcherDelegatingAuthenticationManagerResolverTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/RequestMatcherDelegatingAuthenticationManagerResolverTests.java @@ -23,11 +23,12 @@ import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.mock; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link RequestMatcherDelegatingAuthenticationManagerResolverTests} @@ -44,12 +45,11 @@ public class RequestMatcherDelegatingAuthenticationManagerResolverTests { public void resolveWhenMatchesThenReturnsAuthenticationManager() { RequestMatcherDelegatingAuthenticationManagerResolver resolver = RequestMatcherDelegatingAuthenticationManagerResolver .builder() - .add(new AntPathRequestMatcher("/one/**"), this.one) - .add(new AntPathRequestMatcher("/two/**"), this.two) + .add(PathPatternRequestMatcher.withDefaults().matcher("/one/**"), this.one) + .add(PathPatternRequestMatcher.withDefaults().matcher("/two/**"), this.two) .build(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/one/location"); - request.setServletPath("/one/location"); + MockHttpServletRequest request = get("/one/location").build(); assertThat(resolver.resolve(request)).isEqualTo(this.one); } @@ -57,8 +57,8 @@ public void resolveWhenMatchesThenReturnsAuthenticationManager() { public void resolveWhenDoesNotMatchThenReturnsDefaultAuthenticationManager() { RequestMatcherDelegatingAuthenticationManagerResolver resolver = RequestMatcherDelegatingAuthenticationManagerResolver .builder() - .add(new AntPathRequestMatcher("/one/**"), this.one) - .add(new AntPathRequestMatcher("/two/**"), this.two) + .add(PathPatternRequestMatcher.withDefaults().matcher("/one/**"), this.one) + .add(PathPatternRequestMatcher.withDefaults().matcher("/two/**"), this.two) .build(); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/wrong/location"); diff --git a/web/src/test/java/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilterTests.java index 04f372d71d4..d43144f47a3 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilterTests.java @@ -39,6 +39,7 @@ 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.TestMockHttpServletRequests.post; /** * Tests {@link UsernamePasswordAuthenticationFilter}. @@ -128,10 +129,10 @@ public void testFailedAuthenticationThrowsException() { @Test public void testSecurityContextHolderStrategyUsed() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login"); - request.setServletPath("/login"); - request.addParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod"); - request.addParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala"); + MockHttpServletRequest request = post("/login") + .param(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY, "rod") + .param(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, "koala") + .build(); UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter(); filter.setAuthenticationManager(createAuthenticationManager()); SecurityContextHolderStrategy strategy = spy(SecurityContextHolder.getContextHolderStrategy()); diff --git a/web/src/test/java/org/springframework/security/web/authentication/logout/LogoutHandlerTests.java b/web/src/test/java/org/springframework/security/web/authentication/logout/LogoutHandlerTests.java index 6039fd27a8b..e489b5914e7 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/logout/LogoutHandlerTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/logout/LogoutHandlerTests.java @@ -24,6 +24,8 @@ import org.springframework.security.web.firewall.DefaultHttpFirewall; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * @author Luke Taylor @@ -39,22 +41,20 @@ public void setUp() { @Test public void testRequiresLogoutUrlWorksWithPathParams() { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/context/logout;someparam=blah"); + MockHttpServletRequest request = post().requestUri("/context", "/logout;someparam=blah", null) + .queryString("otherparam=blah") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); - request.setContextPath("/context"); - request.setServletPath("/logout;someparam=blah"); - request.setQueryString("otherparam=blah"); DefaultHttpFirewall fw = new DefaultHttpFirewall(); assertThat(this.filter.requiresLogout(fw.getFirewalledRequest(request), response)).isTrue(); } @Test public void testRequiresLogoutUrlWorksWithQueryParams() { - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context/logout"); - request.setContextPath("/context"); + MockHttpServletRequest request = get().requestUri("/context", "/logout", null) + .queryString("otherparam=blah") + .build(); MockHttpServletResponse response = new MockHttpServletResponse(); - request.setServletPath("/logout"); - request.setQueryString("param=blah"); assertThat(this.filter.requiresLogout(request, response)).isTrue(); } diff --git a/web/src/test/java/org/springframework/security/web/authentication/ott/GenerateOneTimeTokenFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/ott/GenerateOneTimeTokenFilterTests.java index 4c7085ab709..0f329775431 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/ott/GenerateOneTimeTokenFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/ott/GenerateOneTimeTokenFilterTests.java @@ -38,6 +38,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post; /** * Tests for {@link GenerateOneTimeTokenWebFilter} @@ -55,7 +56,7 @@ public class GenerateOneTimeTokenFilterTests { private static final String USERNAME = "user"; - private final MockHttpServletRequest request = new MockHttpServletRequest(); + private MockHttpServletRequest request; private final MockHttpServletResponse response = new MockHttpServletResponse(); @@ -63,9 +64,7 @@ public class GenerateOneTimeTokenFilterTests { @BeforeEach void setup() { - this.request.setMethod("POST"); - this.request.setServletPath("/ott/generate"); - this.request.setRequestURI("/ott/generate"); + this.request = post("/ott/generate").build(); } @Test @@ -87,6 +86,7 @@ void filterWhenUsernameFormParamIsPresentThenSuccess() throws ServletException, void filterWhenUsernameFormParamIsEmptyThenNull() throws ServletException, IOException { given(this.oneTimeTokenService.generate(ArgumentMatchers.any(GenerateOneTimeTokenRequest.class))) .willReturn((new DefaultOneTimeToken(TOKEN, USERNAME, Instant.now()))); + GenerateOneTimeTokenFilter filter = new GenerateOneTimeTokenFilter(this.oneTimeTokenService, this.successHandler); diff --git a/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java index 5598b5543d9..c725b8eb9d4 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java @@ -41,7 +41,7 @@ import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler; import org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler; import org.springframework.security.web.context.SecurityContextRepository; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -60,6 +60,8 @@ */ public class AbstractPreAuthenticatedProcessingFilterTests { + private final PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults(); + private AbstractPreAuthenticatedProcessingFilter filter; @BeforeEach @@ -367,7 +369,7 @@ public void requestNotMatchRequestMatcher() throws Exception { MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter(); - filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/no-matching")); + filter.setRequiresAuthenticationRequestMatcher(this.builder.matcher("/no-matching")); AuthenticationManager am = mock(AuthenticationManager.class); filter.setAuthenticationManager(am); filter.afterPropertiesSet(); @@ -381,7 +383,7 @@ public void requestMatchesRequestMatcher() throws Exception { MockHttpServletResponse response = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter(); - filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/**")); + filter.setRequiresAuthenticationRequestMatcher(this.builder.matcher("/**")); AuthenticationManager am = mock(AuthenticationManager.class); filter.setAuthenticationManager(am); filter.afterPropertiesSet(); diff --git a/web/src/test/java/org/springframework/security/web/authentication/ui/DefaultOneTimeTokenSubmitPageGeneratingFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/ui/DefaultOneTimeTokenSubmitPageGeneratingFilterTests.java index ad38fa6f7cd..18f9af5b6f8 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/ui/DefaultOneTimeTokenSubmitPageGeneratingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/ui/DefaultOneTimeTokenSubmitPageGeneratingFilterTests.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests for {@link DefaultOneTimeTokenSubmitPageGeneratingFilter} @@ -37,7 +38,7 @@ class DefaultOneTimeTokenSubmitPageGeneratingFilterTests { DefaultOneTimeTokenSubmitPageGeneratingFilter filter = new DefaultOneTimeTokenSubmitPageGeneratingFilter(); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/login/ott"); + MockHttpServletRequest request; MockHttpServletResponse response = new MockHttpServletResponse(); @@ -45,9 +46,7 @@ class DefaultOneTimeTokenSubmitPageGeneratingFilterTests { @BeforeEach void setup() { - this.request.setMethod("GET"); - this.request.setServletPath("/login/ott"); - this.request.setRequestURI("/login/ott"); + this.request = get("/login/ott").build(); } @Test @@ -80,10 +79,9 @@ void setLoginProcessingUrlThenUseItForFormAction() throws Exception { @Test void setContextThenGenerates() throws Exception { - this.request.setContextPath("/context"); - this.request.setRequestURI("/context/login/ott"); + MockHttpServletRequest request = get().requestUri("/context", "/login/ott", null).build(); this.filter.setLoginProcessingUrl("/login/another"); - this.filter.doFilterInternal(this.request, this.response, this.filterChain); + this.filter.doFilterInternal(request, this.response, this.filterChain); String response = this.response.getContentAsString(); assertThat(response).contains("
"); } @@ -101,7 +99,7 @@ void filterWhenTokenQueryParamUsesSpecialCharactersThenValueIsEscaped() throws E void filterThenRenders() throws Exception { this.request.setParameter("token", "this<>!@#\""); this.filter.setLoginProcessingUrl("/login/another"); - this.filter.setResolveHiddenInputs((request) -> Map.of("_csrf", "csrf-token-value")); + this.filter.setResolveHiddenInputs((r) -> Map.of("_csrf", "csrf-token-value")); this.filter.doFilterInternal(this.request, this.response, this.filterChain); String response = this.response.getContentAsString(); assertThat(response).isEqualTo( diff --git a/web/src/test/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilterTests.java index faf9f17db41..a05f53392cb 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilterTests.java @@ -46,7 +46,7 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.security.web.context.RequestAttributeSecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository; -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.web.util.WebUtils; @@ -61,6 +61,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link BasicAuthenticationFilter}. @@ -94,8 +95,7 @@ public void clearContext() { @Test public void testFilterIgnoresRequestsContainingNoAuthorizationHeader() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/some_file.html"); + MockHttpServletRequest request = get("/some_file.html").build(); final MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); this.filter.doFilter(request, response, chain); @@ -113,9 +113,8 @@ public void testGettersSetters() { @Test public void testInvalidBasicAuthorizationTokenIsIgnored() throws Exception { String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); final MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); @@ -127,9 +126,8 @@ public void testInvalidBasicAuthorizationTokenIsIgnored() throws Exception { @Test public void invalidBase64IsIgnored() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic NOT_VALID_BASE64"); - request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); final MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); @@ -143,9 +141,8 @@ public void invalidBase64IsIgnored() throws Exception { @Test public void testNormalOperation() throws Exception { String token = "rod:koala"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); // Test assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); FilterChain chain = mock(FilterChain.class); @@ -172,9 +169,8 @@ public void testSecurityContextHolderStrategyUsed() throws Exception { @Test public void doFilterWhenSchemeLowercaseThenCaseInsensitveMatchWorks() throws Exception { String token = "rod:koala"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); // Test assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); FilterChain chain = mock(FilterChain.class); @@ -187,9 +183,8 @@ public void doFilterWhenSchemeLowercaseThenCaseInsensitveMatchWorks() throws Exc @Test public void doFilterWhenSchemeMixedCaseThenCaseInsensitiveMatchWorks() throws Exception { String token = "rod:koala"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "BaSiC " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); FilterChain chain = mock(FilterChain.class); this.filter.doFilter(request, new MockHttpServletResponse(), chain); @@ -200,9 +195,8 @@ public void doFilterWhenSchemeMixedCaseThenCaseInsensitiveMatchWorks() throws Ex @Test public void testOtherAuthorizationSchemeIsIgnored() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "SOME_OTHER_AUTHENTICATION_SCHEME"); - request.setServletPath("/some_file.html"); FilterChain chain = mock(FilterChain.class); this.filter.doFilter(request, new MockHttpServletResponse(), chain); verify(chain).doFilter(any(ServletRequest.class), any(ServletResponse.class)); @@ -222,9 +216,8 @@ public void testStartupDetectsMissingAuthenticationManager() { @Test public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws Exception { String token = "rod:koala"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); final MockHttpServletResponse response1 = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); this.filter.doFilter(request, response1, chain); @@ -240,7 +233,6 @@ public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws chain = mock(FilterChain.class); this.filter.doFilter(request, response2, chain); verify(chain, never()).doFilter(any(ServletRequest.class), any(ServletResponse.class)); - request.setServletPath("/some_file.html"); // Test - the filter chain will not be invoked, as we get a 401 forbidden response MockHttpServletResponse response = response2; assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); @@ -250,9 +242,8 @@ public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken() throws @Test public void testWrongPasswordContinuesFilterChainIfIgnoreFailureIsTrue() throws Exception { String token = "rod:WRONG_PASSWORD"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); this.filter = new BasicAuthenticationFilter(this.manager); assertThat(this.filter.isIgnoreFailure()).isTrue(); @@ -266,9 +257,8 @@ public void testWrongPasswordContinuesFilterChainIfIgnoreFailureIsTrue() throws @Test public void testWrongPasswordReturnsForbiddenIfIgnoreFailureIsFalse() throws Exception { String token = "rod:WRONG_PASSWORD"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); assertThat(this.filter.isIgnoreFailure()).isFalse(); final MockHttpServletResponse response = new MockHttpServletResponse(); @@ -284,9 +274,8 @@ public void testWrongPasswordReturnsForbiddenIfIgnoreFailureIsFalse() throws Exc @Test public void skippedOnErrorDispatch() throws Exception { String token = "bad:credentials"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); request.setAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE, "/error"); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); @@ -307,10 +296,9 @@ public void doFilterWhenTokenAndFilterCharsetMatchDefaultThenAuthenticated() thr given(this.manager.authenticate(not(eq(rodRequest)))).willThrow(new BadCredentialsException("")); this.filter = new BasicAuthenticationFilter(this.manager, new BasicAuthenticationEntryPoint()); String token = "rod:äöü"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token.getBytes(StandardCharsets.UTF_8))); - request.setServletPath("/some_file.html"); MockHttpServletResponse response = new MockHttpServletResponse(); // Test assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); @@ -336,10 +324,9 @@ public void doFilterWhenTokenAndFilterCharsetMatchNonDefaultThenAuthenticated() this.filter = new BasicAuthenticationFilter(this.manager, new BasicAuthenticationEntryPoint()); this.filter.setCredentialsCharset("ISO-8859-1"); String token = "rod:äöü"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token.getBytes(StandardCharsets.ISO_8859_1))); - request.setServletPath("/some_file.html"); MockHttpServletResponse response = new MockHttpServletResponse(); // Test assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); @@ -367,10 +354,9 @@ public void doFilterWhenTokenAndFilterCharsetDoNotMatchThenUnauthorized() throws this.filter = new BasicAuthenticationFilter(this.manager, new BasicAuthenticationEntryPoint()); this.filter.setCredentialsCharset("ISO-8859-1"); String token = "rod:äöü"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token.getBytes(StandardCharsets.UTF_8))); - request.setServletPath("/some_file.html"); MockHttpServletResponse response = new MockHttpServletResponse(); // Test assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); @@ -383,9 +369,8 @@ public void doFilterWhenTokenAndFilterCharsetDoNotMatchThenUnauthorized() throws @Test public void requestWhenEmptyBasicAuthorizationHeaderTokenThenUnauthorized() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic "); - request.setServletPath("/some_file.html"); request.setSession(new MockHttpSession()); final MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain chain = mock(FilterChain.class); @@ -401,9 +386,8 @@ public void requestWhenSecurityContextRepository() throws Exception { SecurityContextRepository securityContextRepository = mock(SecurityContextRepository.class); this.filter.setSecurityContextRepository(securityContextRepository); String token = "rod:koala"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/some_file.html").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/some_file.html"); MockHttpServletResponse response = new MockHttpServletResponse(); // Test assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); @@ -496,9 +480,8 @@ public void doFilterWhenUsernameChangesAndNotUsernamePasswordAuthenticationToken public void doFilterWhenCustomAuthenticationConverterThatIgnoresRequestThenIgnores() throws Exception { this.filter.setAuthenticationConverter(new TestAuthenticationConverter()); String token = "rod:koala"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/ignored").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/ignored"); FilterChain filterChain = mock(FilterChain.class); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, filterChain); @@ -513,9 +496,8 @@ public void doFilterWhenCustomAuthenticationConverterThatIgnoresRequestThenIgnor public void doFilterWhenCustomAuthenticationConverterRequestThenAuthenticate() throws Exception { this.filter.setAuthenticationConverter(new TestAuthenticationConverter()); String token = "rod:koala"; - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = get("/ok").build(); request.addHeader("Authorization", "Basic " + CodecTestUtils.encodeBase64(token)); - request.setServletPath("/ok"); FilterChain filterChain = mock(FilterChain.class); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, filterChain); @@ -531,7 +513,7 @@ public void setAuthenticationConverterWhenNullThenException() { static class TestAuthenticationConverter implements AuthenticationConverter { - private final RequestMatcher matcher = AntPathRequestMatcher.antMatcher("/ignored"); + private final RequestMatcher matcher = PathPatternRequestMatcher.withDefaults().matcher("/ignored"); private final BasicAuthenticationConverter delegate = new BasicAuthenticationConverter(); diff --git a/web/src/test/java/org/springframework/security/web/authentication/www/DigestAuthenticationFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/www/DigestAuthenticationFilterTests.java index 230c554fcd8..c3375abf29c 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/www/DigestAuthenticationFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/www/DigestAuthenticationFilterTests.java @@ -53,6 +53,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * Tests {@link DigestAuthenticationFilter}. @@ -131,8 +132,7 @@ public void setUp() { this.filter = new DigestAuthenticationFilter(); this.filter.setUserDetailsService(uds); this.filter.setAuthenticationEntryPoint(ep); - this.request = new MockHttpServletRequest("GET", REQUEST_URI); - this.request.setServletPath(REQUEST_URI); + this.request = get(REQUEST_URI).build(); } @Test diff --git a/web/src/test/java/org/springframework/security/web/debug/DebugFilterTests.java b/web/src/test/java/org/springframework/security/web/debug/DebugFilterTests.java index 683db01360a..1088f993e5b 100644 --- a/web/src/test/java/org/springframework/security/web/debug/DebugFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/debug/DebugFilterTests.java @@ -41,6 +41,7 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * @author Rob Winch @@ -120,10 +121,7 @@ public void doFilterDoesNotWrapWithDebugRequestWrapperAgain() throws Exception { @Test public void doFilterLogsProperly() throws Exception { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setMethod("GET"); - request.setServletPath("/path"); - request.setPathInfo("/"); + MockHttpServletRequest request = get().requestUri(null, "/path", "/").build(); request.addHeader("A", "A Value"); request.addHeader("A", "Another Value"); request.addHeader("B", "B Value"); diff --git a/web/src/test/java/org/springframework/security/web/firewall/DefaultHttpFirewallTests.java b/web/src/test/java/org/springframework/security/web/firewall/DefaultHttpFirewallTests.java index c7ce4d72f33..00f656816b0 100644 --- a/web/src/test/java/org/springframework/security/web/firewall/DefaultHttpFirewallTests.java +++ b/web/src/test/java/org/springframework/security/web/firewall/DefaultHttpFirewallTests.java @@ -21,6 +21,7 @@ import org.springframework.mock.web.MockHttpServletRequest; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * @author Luke Taylor @@ -34,8 +35,7 @@ public class DefaultHttpFirewallTests { public void unnormalizedPathsAreRejected() { DefaultHttpFirewall fw = new DefaultHttpFirewall(); for (String path : this.unnormalizedPaths) { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath(path); + MockHttpServletRequest request = get().requestUri(path).build(); assertThatExceptionOfType(RequestRejectedException.class) .isThrownBy(() -> fw.getFirewalledRequest(request)); request.setPathInfo(path); diff --git a/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java b/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java index f5406f00943..e7a46bfe542 100644 --- a/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java +++ b/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; /** * @author Rob Winch @@ -112,8 +113,7 @@ public void getFirewalledRequestWhenContextPathNotNormalizedThenThrowsRequestRej @Test public void getFirewalledRequestWhenServletPathNotNormalizedThenThrowsRequestRejectedException() { for (String path : this.unnormalizedPaths) { - this.request = new MockHttpServletRequest("GET", ""); - this.request.setServletPath(path); + this.request = get().requestUri(path).build(); assertThatExceptionOfType(RequestRejectedException.class) .isThrownBy(() -> this.firewall.getFirewalledRequest(this.request)); } diff --git a/web/src/test/java/org/springframework/security/web/servlet/TestMockHttpServletRequests.java b/web/src/test/java/org/springframework/security/web/servlet/TestMockHttpServletRequests.java new file mode 100644 index 00000000000..017397640c0 --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/servlet/TestMockHttpServletRequests.java @@ -0,0 +1,169 @@ +/* + * Copyright 2004-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.web.servlet; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.springframework.http.HttpMethod; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.util.StringUtils; + +public final class TestMockHttpServletRequests { + + private TestMockHttpServletRequests() { + + } + + public static Builder get() { + return new Builder(HttpMethod.GET); + } + + public static Builder get(String url) { + return get().applyUrl(url); + } + + public static Builder post() { + return new Builder(HttpMethod.POST); + } + + public static Builder post(String url) { + return post().applyUrl(url); + } + + public static Builder request(String method) { + return new Builder(HttpMethod.valueOf(method)); + } + + public static final class Builder { + + private static final Pattern URL = Pattern.compile("((?https?)://)?" + + "((?[^:/]+)(:(?\\d+))?)?" + "(?[^?]+)?" + "(\\?(?.*))?"); + + private final HttpMethod method; + + private String requestUri; + + private final Map parameters = new LinkedHashMap<>(); + + private String scheme = MockHttpServletRequest.DEFAULT_SCHEME; + + private int port = MockHttpServletRequest.DEFAULT_SERVER_PORT; + + private String hostname = MockHttpServletRequest.DEFAULT_SERVER_NAME; + + private String contextPath; + + private String servletPath; + + private String pathInfo; + + private String queryString; + + private Builder(HttpMethod method) { + this.method = method; + } + + private Builder applyUrl(String url) { + Matcher matcher = URL.matcher(url); + if (matcher.matches()) { + applyElement(this::scheme, matcher.group("scheme")); + applyElement(this::port, matcher.group("port")); + applyElement(this::serverName, matcher.group("hostname")); + applyElement(this::requestUri, matcher.group("path")); + applyElement(this::queryString, matcher.group("query")); + } + return this; + } + + private void applyElement(Consumer apply, T value) { + if (value != null) { + apply.accept(value); + } + } + + public Builder requestUri(String contextPath, String servletPath, String pathInfo) { + this.contextPath = contextPath; + this.servletPath = servletPath; + this.pathInfo = pathInfo; + this.requestUri = Stream.of(contextPath, servletPath, pathInfo) + .filter(StringUtils::hasText) + .collect(Collectors.joining()); + return this; + } + + public Builder requestUri(String requestUri) { + return requestUri(null, requestUri, null); + } + + public Builder param(String name, String value) { + this.parameters.put(name, value); + return this; + } + + private Builder port(String port) { + if (port != null) { + this.port = Integer.parseInt(port); + } + return this; + } + + public Builder port(int port) { + this.port = port; + return this; + } + + public Builder queryString(String queryString) { + this.queryString = queryString; + return this; + } + + public Builder scheme(String scheme) { + this.scheme = scheme; + return this; + } + + public Builder serverName(String serverName) { + this.hostname = serverName; + return this; + } + + public MockHttpServletRequest build() { + MockHttpServletRequest request = new MockHttpServletRequest(); + applyElement(request::setContextPath, this.contextPath); + applyElement(request::setContextPath, this.contextPath); + applyElement(request::setMethod, this.method.name()); + applyElement(request::setParameters, this.parameters); + applyElement(request::setPathInfo, this.pathInfo); + applyElement(request::setServletPath, this.servletPath); + applyElement(request::setScheme, this.scheme); + applyElement(request::setServerPort, this.port); + applyElement(request::setServerName, this.hostname); + applyElement(request::setQueryString, this.queryString); + applyElement(request::setRequestURI, this.requestUri); + request.setSecure("https".equals(this.scheme)); + return request; + } + + } + +} diff --git a/web/src/test/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcherTests.java b/web/src/test/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcherTests.java deleted file mode 100644 index 047f42604ca..00000000000 --- a/web/src/test/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcherTests.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2012-2022 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.web.servlet.util.matcher; - -import java.util.Collections; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import org.springframework.http.HttpMethod; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; -import org.springframework.web.servlet.handler.MatchableHandlerMapping; -import org.springframework.web.servlet.handler.RequestMatchResult; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -/** - * @author Rob Winch - * @author Eddú Meléndez - * @author Evgeniy Cheban - */ -@ExtendWith(MockitoExtension.class) -public class MvcRequestMatcherTests { - - @Mock - HandlerMappingIntrospector introspector; - - @Mock - MatchableHandlerMapping mapping; - - @Mock - RequestMatchResult result; - - @Captor - ArgumentCaptor pattern; - - MockHttpServletRequest request; - - MvcRequestMatcher matcher; - - @BeforeEach - public void setup() { - this.request = new MockHttpServletRequest(); - this.request.setMethod("GET"); - this.request.setServletPath("/path"); - this.matcher = new MvcRequestMatcher(this.introspector, "/path"); - } - - @Test - public void extractUriTemplateVariablesSuccess() throws Exception { - this.matcher = new MvcRequestMatcher(this.introspector, "/{p}"); - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(null); - assertThat(this.matcher.extractUriTemplateVariables(this.request)).containsEntry("p", "path"); - assertThat(this.matcher.matcher(this.request).getVariables()).containsEntry("p", "path"); - } - - @Test - public void extractUriTemplateVariablesFail() throws Exception { - given(this.result.extractUriTemplateVariables()).willReturn(Collections.emptyMap()); - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(this.mapping); - given(this.mapping.match(eq(this.request), this.pattern.capture())).willReturn(this.result); - assertThat(this.matcher.extractUriTemplateVariables(this.request)).isEmpty(); - assertThat(this.matcher.matcher(this.request).getVariables()).isEmpty(); - } - - @Test - public void extractUriTemplateVariablesDefaultSuccess() throws Exception { - this.matcher = new MvcRequestMatcher(this.introspector, "/{p}"); - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(null); - assertThat(this.matcher.extractUriTemplateVariables(this.request)).containsEntry("p", "path"); - assertThat(this.matcher.matcher(this.request).getVariables()).containsEntry("p", "path"); - } - - @Test - public void extractUriTemplateVariablesDefaultFail() throws Exception { - this.matcher = new MvcRequestMatcher(this.introspector, "/nomatch/{p}"); - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(null); - assertThat(this.matcher.extractUriTemplateVariables(this.request)).isEmpty(); - assertThat(this.matcher.matcher(this.request).getVariables()).isEmpty(); - } - - @Test - public void matchesServletPathTrue() throws Exception { - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(this.mapping); - given(this.mapping.match(eq(this.request), this.pattern.capture())).willReturn(this.result); - this.matcher.setServletPath("/spring"); - this.request.setServletPath("/spring"); - assertThat(this.matcher.matches(this.request)).isTrue(); - assertThat(this.pattern.getValue()).isEqualTo("/path"); - } - - @Test - public void matchesServletPathFalse() { - this.matcher.setServletPath("/spring"); - this.request.setServletPath("/"); - assertThat(this.matcher.matches(this.request)).isFalse(); - } - - @Test - public void matchesPathOnlyTrue() throws Exception { - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(this.mapping); - given(this.mapping.match(eq(this.request), this.pattern.capture())).willReturn(this.result); - assertThat(this.matcher.matches(this.request)).isTrue(); - assertThat(this.pattern.getValue()).isEqualTo("/path"); - } - - @Test - public void matchesDefaultMatches() throws Exception { - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(null); - assertThat(this.matcher.matches(this.request)).isTrue(); - } - - @Test - public void matchesDefaultDoesNotMatch() throws Exception { - this.request.setServletPath("/other"); - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(null); - assertThat(this.matcher.matches(this.request)).isFalse(); - } - - @Test - public void matchesPathOnlyFalse() throws Exception { - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(this.mapping); - assertThat(this.matcher.matches(this.request)).isFalse(); - } - - @Test - public void matchesMethodAndPathTrue() throws Exception { - this.matcher.setMethod(HttpMethod.GET); - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(this.mapping); - given(this.mapping.match(eq(this.request), this.pattern.capture())).willReturn(this.result); - assertThat(this.matcher.matches(this.request)).isTrue(); - assertThat(this.pattern.getValue()).isEqualTo("/path"); - } - - @Test - public void matchesMethodAndPathFalseMethod() { - this.matcher.setMethod(HttpMethod.POST); - assertThat(this.matcher.matches(this.request)).isFalse(); - // method compare should be done first since faster - verifyNoMoreInteractions(this.introspector); - } - - /** - * Malicious users can specify any HTTP Method to create a stacktrace and try to - * expose useful information about the system. We should ensure we ignore invalid HTTP - * methods. - */ - @Test - public void matchesInvalidMethodOnRequest() { - this.matcher.setMethod(HttpMethod.GET); - this.request.setMethod("invalid"); - assertThat(this.matcher.matches(this.request)).isFalse(); - // method compare should be done first since faster - verifyNoMoreInteractions(this.introspector); - } - - @Test - public void matchesMethodAndPathFalsePath() throws Exception { - this.matcher.setMethod(HttpMethod.GET); - given(this.introspector.getMatchableHandlerMapping(this.request)).willReturn(this.mapping); - assertThat(this.matcher.matches(this.request)).isFalse(); - } - - @Test - public void matchesGetMatchableHandlerMappingNull() { - assertThat(this.matcher.matches(this.request)).isTrue(); - } - - @Test - public void matchesGetMatchableHandlerMappingThrows() throws Exception { - given(this.introspector.getMatchableHandlerMapping(this.request)) - .willThrow(new HttpRequestMethodNotSupportedException(this.request.getMethod())); - assertThat(this.matcher.matches(this.request)).isTrue(); - } - - @Test - public void toStringWhenAll() { - this.matcher.setMethod(HttpMethod.GET); - this.matcher.setServletPath("/spring"); - assertThat(this.matcher.toString()).isEqualTo("Mvc [pattern='/path', servletPath='/spring', GET]"); - } - - @Test - public void toStringWhenHttpMethod() { - this.matcher.setMethod(HttpMethod.GET); - assertThat(this.matcher.toString()).isEqualTo("Mvc [pattern='/path', GET]"); - } - - @Test - public void toStringWhenServletPath() { - this.matcher.setServletPath("/spring"); - assertThat(this.matcher.toString()).isEqualTo("Mvc [pattern='/path', servletPath='/spring']"); - } - - @Test - public void toStringWhenOnlyPattern() { - assertThat(this.matcher.toString()).isEqualTo("Mvc [pattern='/path']"); - } - - @Test - public void matcherWhenMethodNotMatchesThenNotMatchResult() { - this.matcher.setMethod(HttpMethod.POST); - assertThat(this.matcher.matcher(this.request).isMatch()).isFalse(); - } - - @Test - public void matcherWhenMethodMatchesThenMatchResult() { - this.matcher.setMethod(HttpMethod.GET); - assertThat(this.matcher.matcher(this.request).isMatch()).isTrue(); - } - - @Test - public void matcherWhenServletPathNotMatchesThenNotMatchResult() { - this.matcher.setServletPath("/spring"); - assertThat(this.matcher.matcher(this.request).isMatch()).isFalse(); - } - - @Test - public void matcherWhenServletPathMatchesThenMatchResult() { - this.matcher.setServletPath("/path"); - assertThat(this.matcher.matcher(this.request).isMatch()).isTrue(); - } - - @Test - public void builderWhenServletPathThenServletPathPresent() { - MvcRequestMatcher matcher = new MvcRequestMatcher.Builder(this.introspector).servletPath("/path") - .pattern("/endpoint"); - assertThat(matcher.getServletPath()).isEqualTo("/path"); - assertThat(ReflectionTestUtils.getField(matcher, "pattern")).isEqualTo("/endpoint"); - assertThat(ReflectionTestUtils.getField(matcher, "method")).isNull(); - } - - @Test - public void builderWhenPatternThenPatternPresent() { - MvcRequestMatcher matcher = new MvcRequestMatcher.Builder(this.introspector).pattern("/endpoint"); - assertThat(matcher.getServletPath()).isNull(); - assertThat(ReflectionTestUtils.getField(matcher, "pattern")).isEqualTo("/endpoint"); - assertThat(ReflectionTestUtils.getField(matcher, "method")).isNull(); - } - - @Test - public void builderWhenMethodAndPatternThenMethodAndPatternPresent() { - MvcRequestMatcher matcher = new MvcRequestMatcher.Builder(this.introspector).pattern(HttpMethod.GET, - "/endpoint"); - assertThat(matcher.getServletPath()).isNull(); - assertThat(ReflectionTestUtils.getField(matcher, "pattern")).isEqualTo("/endpoint"); - assertThat(ReflectionTestUtils.getField(matcher, "method")).isEqualTo(HttpMethod.GET); - } - -} diff --git a/web/src/test/java/org/springframework/security/web/util/matcher/AndRequestMatcherTests.java b/web/src/test/java/org/springframework/security/web/util/matcher/AndRequestMatcherTests.java index 62b3781790e..4dc56d8773d 100644 --- a/web/src/test/java/org/springframework/security/web/util/matcher/AndRequestMatcherTests.java +++ b/web/src/test/java/org/springframework/security/web/util/matcher/AndRequestMatcherTests.java @@ -27,6 +27,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher.MatchResult; import static org.assertj.core.api.Assertions.assertThat; @@ -59,7 +60,7 @@ public void constructorNullArray() { @Test public void constructorListOfDoesNotThrowNullPointer() { - new AndRequestMatcher(List.of(new AntPathRequestMatcher("/test"))); + new AndRequestMatcher(List.of(PathPatternRequestMatcher.withDefaults().matcher("/test"))); } @Test diff --git a/web/src/test/java/org/springframework/security/web/util/matcher/AntPathRequestMatcherTests.java b/web/src/test/java/org/springframework/security/web/util/matcher/AntPathRequestMatcherTests.java deleted file mode 100644 index 09c4d194a78..00000000000 --- a/web/src/test/java/org/springframework/security/web/util/matcher/AntPathRequestMatcherTests.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright 2002-2022 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.web.util.matcher; - -import jakarta.servlet.http.HttpServletRequest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import org.springframework.http.HttpMethod; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.web.util.UrlPathHelper; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.mockito.BDDMockito.given; -import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; - -/** - * @author Luke Taylor - * @author Rob Winch - * @author Evgeniy Cheban - */ -@ExtendWith(MockitoExtension.class) -public class AntPathRequestMatcherTests { - - @Mock - private HttpServletRequest request; - - @Test - public void matchesWhenUrlPathHelperThenMatchesOnRequestUri() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/foo/bar", null, true, new UrlPathHelper()); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/bar"); - assertThat(matcher.matches(request)).isTrue(); - } - - @Test - public void singleWildcardMatchesAnyPath() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/**"); - assertThat(matcher.getPattern()).isEqualTo("/**"); - assertThat(matcher.matches(createRequest("/blah"))).isTrue(); - matcher = new AntPathRequestMatcher("**"); - assertThat(matcher.matches(createRequest("/blah"))).isTrue(); - assertThat(matcher.matches(createRequest(""))).isTrue(); - } - - @Test - public void trailingWildcardMatchesCorrectly() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/blah/blAh/**", null, false); - assertThat(matcher.matches(createRequest("/BLAH/blah"))).isTrue(); - assertThat(matcher.matches(createRequest("/blah/bleh"))).isFalse(); - assertThat(matcher.matches(createRequest("/blah/blah/"))).isTrue(); - assertThat(matcher.matches(createRequest("/blah/blah/xxx"))).isTrue(); - assertThat(matcher.matches(createRequest("/blah/blaha"))).isFalse(); - assertThat(matcher.matches(createRequest("/blah/bleh/"))).isFalse(); - MockHttpServletRequest request = createRequest("/blah/"); - request.setPathInfo("blah/bleh"); - assertThat(matcher.matches(request)).isTrue(); - matcher = new AntPathRequestMatcher("/bl?h/blAh/**", null, false); - assertThat(matcher.matches(createRequest("/BLAH/Blah/aaa/"))).isTrue(); - assertThat(matcher.matches(createRequest("/bleh/Blah"))).isTrue(); - matcher = new AntPathRequestMatcher("/blAh/**/blah/**", null, false); - assertThat(matcher.matches(createRequest("/blah/blah"))).isTrue(); - assertThat(matcher.matches(createRequest("/blah/bleh"))).isFalse(); - assertThat(matcher.matches(createRequest("/blah/aaa/blah/bbb"))).isTrue(); - } - - @Test - public void trailingWildcardWithVariableMatchesCorrectly() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/{id}/blAh/**", null, false); - assertThat(matcher.matches(createRequest("/1234/blah"))).isTrue(); - assertThat(matcher.matches(createRequest("/4567/bleh"))).isFalse(); - assertThat(matcher.matches(createRequest("/paskos/blah/"))).isTrue(); - assertThat(matcher.matches(createRequest("/12345/blah/xxx"))).isTrue(); - assertThat(matcher.matches(createRequest("/12345/blaha"))).isFalse(); - assertThat(matcher.matches(createRequest("/paskos/bleh/"))).isFalse(); - } - - @Test - public void nontrailingWildcardWithVariableMatchesCorrectly() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/**/{id}"); - assertThat(matcher.matches(createRequest("/blah/1234"))).isTrue(); - assertThat(matcher.matches(createRequest("/bleh/4567"))).isTrue(); - assertThat(matcher.matches(createRequest("/paskos/blah/"))).isFalse(); - assertThat(matcher.matches(createRequest("/12345/blah/xxx"))).isTrue(); - assertThat(matcher.matches(createRequest("/12345/blaha"))).isTrue(); - assertThat(matcher.matches(createRequest("/paskos/bleh/"))).isFalse(); - } - - @Test - public void requestHasNullMethodMatches() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*", "GET"); - HttpServletRequest request = createRequestWithNullMethod("/something/here"); - assertThat(matcher.matches(request)).isTrue(); - } - - // SEC-2084 - @Test - public void requestHasNullMethodNoMatch() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*", "GET"); - HttpServletRequest request = createRequestWithNullMethod("/nomatch"); - assertThat(matcher.matches(request)).isFalse(); - } - - @Test - public void requestHasNullMethodAndNullMatcherMatches() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*"); - MockHttpServletRequest request = createRequest("/something/here"); - request.setMethod(null); - assertThat(matcher.matches(request)).isTrue(); - } - - @Test - public void requestHasNullMethodAndNullMatcherNoMatch() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/something/*"); - MockHttpServletRequest request = createRequest("/nomatch"); - request.setMethod(null); - assertThat(matcher.matches(request)).isFalse(); - } - - @Test - public void exactMatchOnlyMatchesIdenticalPath() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/login.html"); - assertThat(matcher.matches(createRequest("/login.html"))).isTrue(); - assertThat(matcher.matches(createRequest("/login.html/"))).isFalse(); - assertThat(matcher.matches(createRequest("/login.html/blah"))).isFalse(); - } - - @Test - public void httpMethodSpecificMatchOnlyMatchesRequestsWithCorrectMethod() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/blah", "GET"); - MockHttpServletRequest request = createRequest("/blah"); - request.setMethod("GET"); - assertThat(matcher.matches(request)).isTrue(); - request.setMethod("POST"); - assertThat(matcher.matches(request)).isFalse(); - } - - @Test - public void caseSensitive() { - MockHttpServletRequest request = createRequest("/UPPER"); - assertThat(new AntPathRequestMatcher("/upper", null, true).matches(request)).isFalse(); - assertThat(new AntPathRequestMatcher("/upper", "POST", true).matches(request)).isFalse(); - assertThat(new AntPathRequestMatcher("/upper", "GET", true).matches(request)).isFalse(); - assertThat(new AntPathRequestMatcher("/upper", null, false).matches(request)).isTrue(); - assertThat(new AntPathRequestMatcher("/upper", "POST", false).matches(request)).isTrue(); - } - - @Test - public void spacesInPathSegmentsAreNotIgnored() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/path/*/bar"); - MockHttpServletRequest request = createRequest("/path /foo/bar"); - assertThat(matcher.matches(request)).isFalse(); - matcher = new AntPathRequestMatcher("/path/foo"); - request = createRequest("/path /foo"); - assertThat(matcher.matches(request)).isFalse(); - } - - @Test - public void equalsBehavesCorrectly() { - // Both universal wildcard options should be equal - assertThat(new AntPathRequestMatcher("**")).isEqualTo(new AntPathRequestMatcher("/**")); - assertThat(new AntPathRequestMatcher("/xyz")).isEqualTo(new AntPathRequestMatcher("/xyz")); - assertThat(new AntPathRequestMatcher("/xyz", "POST")).isEqualTo(new AntPathRequestMatcher("/xyz", "POST")); - assertThat(new AntPathRequestMatcher("/xyz", "POST")).isNotEqualTo(new AntPathRequestMatcher("/xyz", "GET")); - assertThat(new AntPathRequestMatcher("/xyz")).isNotEqualTo(new AntPathRequestMatcher("/xxx")); - assertThat(new AntPathRequestMatcher("/xyz").equals(AnyRequestMatcher.INSTANCE)).isFalse(); - assertThat(new AntPathRequestMatcher("/xyz", "GET", false)) - .isNotEqualTo(new AntPathRequestMatcher("/xyz", "GET", true)); - } - - @Test - public void toStringIsOk() { - new AntPathRequestMatcher("/blah").toString(); - new AntPathRequestMatcher("/blah", "GET").toString(); - } - - // SEC-2831 - @Test - public void matchesWithInvalidMethod() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/blah", "GET"); - MockHttpServletRequest request = createRequest("/blah"); - request.setMethod("INVALID"); - assertThat(matcher.matches(request)).isFalse(); - } - - // gh-9285 - @Test - public void matcherWhenMatchAllPatternThenMatchResult() { - AntPathRequestMatcher matcher = new AntPathRequestMatcher("/**"); - MockHttpServletRequest request = createRequest("/blah"); - assertThat(matcher.matcher(request).isMatch()).isTrue(); - } - - @Test - public void staticAntMatcherWhenPatternProvidedThenPattern() { - AntPathRequestMatcher matcher = antMatcher("/path"); - assertThat(matcher.getPattern()).isEqualTo("/path"); - } - - @Test - public void staticAntMatcherWhenMethodProvidedThenMatchAll() { - AntPathRequestMatcher matcher = antMatcher(HttpMethod.GET); - assertThat(ReflectionTestUtils.getField(matcher, "httpMethod")).isEqualTo(HttpMethod.GET); - } - - @Test - public void staticAntMatcherWhenMethodAndPatternProvidedThenMatchAll() { - AntPathRequestMatcher matcher = antMatcher(HttpMethod.POST, "/path"); - assertThat(matcher.getPattern()).isEqualTo("/path"); - assertThat(ReflectionTestUtils.getField(matcher, "httpMethod")).isEqualTo(HttpMethod.POST); - } - - @Test - public void staticAntMatcherWhenMethodNullThenException() { - assertThatIllegalArgumentException().isThrownBy(() -> antMatcher((HttpMethod) null)) - .withMessage("method cannot be null"); - } - - @Test - public void staticAntMatcherWhenPatternNullThenException() { - assertThatIllegalArgumentException().isThrownBy(() -> antMatcher((String) null)) - .withMessage("pattern cannot be empty"); - } - - @Test - public void forMethodWhenMethodThenMatches() { - AntPathRequestMatcher matcher = antMatcher(HttpMethod.POST); - MockHttpServletRequest request = createRequest("/path"); - assertThat(matcher.matches(request)).isTrue(); - request.setServletPath("/another-path/second"); - assertThat(matcher.matches(request)).isTrue(); - request.setMethod("GET"); - assertThat(matcher.matches(request)).isFalse(); - } - - private HttpServletRequest createRequestWithNullMethod(String path) { - given(this.request.getServletPath()).willReturn(path); - return this.request; - } - - private MockHttpServletRequest createRequest(String path) { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setQueryString("doesntMatter"); - request.setServletPath(path); - request.setMethod("POST"); - return request; - } - -} diff --git a/web/src/test/java/org/springframework/security/web/util/matcher/OrRequestMatcherTests.java b/web/src/test/java/org/springframework/security/web/util/matcher/OrRequestMatcherTests.java index 72dd4162bd4..4a1bc7ccb6a 100644 --- a/web/src/test/java/org/springframework/security/web/util/matcher/OrRequestMatcherTests.java +++ b/web/src/test/java/org/springframework/security/web/util/matcher/OrRequestMatcherTests.java @@ -27,6 +27,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher.MatchResult; import static org.assertj.core.api.Assertions.assertThat; @@ -60,7 +61,7 @@ public void constructorNullArray() { @Test public void constructorListOfDoesNotThrowNullPointer() { - new OrRequestMatcher(List.of(new AntPathRequestMatcher("/test"))); + new OrRequestMatcher(List.of(PathPatternRequestMatcher.withDefaults().matcher("/test"))); } @Test diff --git a/web/src/test/java/org/springframework/security/web/util/matcher/RegexRequestMatcherTests.java b/web/src/test/java/org/springframework/security/web/util/matcher/RegexRequestMatcherTests.java index 8263b776f07..96713037508 100644 --- a/web/src/test/java/org/springframework/security/web/util/matcher/RegexRequestMatcherTests.java +++ b/web/src/test/java/org/springframework/security/web/util/matcher/RegexRequestMatcherTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.BDDMockito.given; +import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get; import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher; /** @@ -50,8 +51,7 @@ public void doesntMatchIfHttpMethodIsDifferent() { @Test public void matchesIfHttpMethodAndPathMatch() { RegexRequestMatcher matcher = new RegexRequestMatcher(".*", "GET"); - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/anything"); - request.setServletPath("/anything"); + MockHttpServletRequest request = get("/anything").build(); assertThat(matcher.matches(request)).isTrue(); }