Skip to content

Migrate from AntPathRequestMatcher to PathPatternRequestMatcher #45163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
Expand Down Expand Up @@ -183,15 +184,12 @@ static class IgnoredCloudFoundryPathsWebSecurityCustomizer implements WebSecurit
}

@Override
@SuppressWarnings("removal")
public void customize(WebSecurity web) {
List<RequestMatcher> requestMatchers = new ArrayList<>();
this.pathMappedEndpoints.getAllPaths()
.forEach((path) -> requestMatchers
.add(new org.springframework.security.web.util.matcher.AntPathRequestMatcher(path + "/**")));
requestMatchers.add(new org.springframework.security.web.util.matcher.AntPathRequestMatcher(BASE_PATH));
requestMatchers
.add(new org.springframework.security.web.util.matcher.AntPathRequestMatcher(BASE_PATH + "/"));
.forEach((path) -> requestMatchers.add(PathPatternRequestMatcher.withDefaults().matcher(path + "/**")));
requestMatchers.add(PathPatternRequestMatcher.withDefaults().matcher(BASE_PATH));
requestMatchers.add(PathPatternRequestMatcher.withDefaults().matcher(BASE_PATH + "/"));
web.ignoring().requestMatchers(new OrRequestMatcher(requestMatchers));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
import java.util.function.Function;

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.RequestMatcher;

/**
* {@link RequestMatcherProvider} that provides an {@link AntPathRequestMatcher}.
* {@link RequestMatcherProvider} that provides an {@link PathPatternRequestMatcher}.
*
* @author Madhura Bhave
* @author Chris Bono
Expand All @@ -37,11 +37,9 @@ class AntPathRequestMatcherProvider implements RequestMatcherProvider {
}

@Override
@SuppressWarnings("removal")
public RequestMatcher getRequestMatcher(String pattern, HttpMethod httpMethod) {
String path = this.pathFactory.apply(pattern);
return new org.springframework.security.web.util.matcher.AntPathRequestMatcher(path,
(httpMethod != null) ? httpMethod.name() : null);
return PathPatternRequestMatcher.withDefaults().matcher(httpMethod, path);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.http.HttpMethod;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -231,14 +232,12 @@ protected List<RequestMatcher> getLinksMatchers(RequestMatcherFactory requestMat
return linksMatchers;
}

@SuppressWarnings("removal")
protected RequestMatcherProvider getRequestMatcherProvider(WebApplicationContext context) {
try {
return getRequestMatcherProviderBean(context);
}
catch (NoSuchBeanDefinitionException ex) {
return (pattern, method) -> new org.springframework.security.web.util.matcher.AntPathRequestMatcher(
pattern, (method != null) ? method.name() : null);
return (pattern, method) -> PathPatternRequestMatcher.withDefaults().matcher(method, pattern);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-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.
Expand Down Expand Up @@ -182,8 +182,10 @@ void cloudFoundryPathsIgnoredBySpringSecurity() {
testCloudFoundrySecurity(request, BASE_PATH + "/test", chain);
testCloudFoundrySecurity(request, BASE_PATH + "/test/a", chain);
request.setServletPath(BASE_PATH + "/other-path");
request.setRequestURI(BASE_PATH + "/other-path");
assertThat(chain.matches(request)).isFalse();
request.setServletPath("/some-other-path");
request.setRequestURI("/some-other-path");
assertThat(chain.matches(request)).isFalse();
});
}
Expand Down Expand Up @@ -211,7 +213,7 @@ private FilterChainProxy getFilterChainProxy(Filter filter) {

private static void testCloudFoundrySecurity(MockHttpServletRequest request, String servletPath,
SecurityFilterChain chain) {
request.setServletPath(servletPath);
request.setRequestURI(servletPath);
assertThat(chain.matches(request)).isTrue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ private MockHttpServletRequest mockRequest(HttpMethod httpMethod, String servlet
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
MockHttpServletRequest request = new MockHttpServletRequest(servletContext);
if (servletPath != null) {
request.setServletPath(servletPath);
request.setRequestURI(servletPath);
}
if (httpMethod != null) {
request.setMethod(httpMethod.name());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.WebApplicationContext;

Expand Down Expand Up @@ -206,7 +206,7 @@ private HttpStatus getResponseStatus(AssertableWebApplicationContext context, St
MockHttpServletResponse response = new MockHttpServletResponse();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
MockHttpServletRequest request = new MockHttpServletRequest(servletContext);
request.setServletPath(path);
request.setRequestURI(path);
request.setMethod("GET");
filterChainProxy.doFilter(request, response, new MockFilterChain());
return HttpStatus.valueOf(response.getStatus());
Expand All @@ -216,10 +216,9 @@ private HttpStatus getResponseStatus(AssertableWebApplicationContext context, St
static class CustomSecurityConfiguration {

@Bean
@SuppressWarnings("removal")
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> {
requests.requestMatchers(new AntPathRequestMatcher("/foo")).permitAll();
requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/foo")).permitAll();
requests.anyRequest().authenticated();
});
http.formLogin(withDefaults());
Expand All @@ -246,9 +245,8 @@ static class TestRemoteDevToolsSecurityFilterChainConfig extends TestSecurityFil

@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER - 1)
@SuppressWarnings("removal")
SecurityFilterChain testRemoteDevToolsSecurityFilterChain(HttpSecurity http) throws Exception {
http.securityMatcher(new AntPathRequestMatcher("/**"));
http.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/**"));
http.authorizeHttpRequests((requests) -> requests.anyRequest().anonymous());
http.csrf((csrf) -> csrf.disable());
return http.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.util.pattern.PathPatternParser;

import static org.assertj.core.api.Assertions.assertThat;

Expand Down Expand Up @@ -60,7 +61,8 @@ void registersRequestMatcherProviderIfMvcPresent() {
this.contextRunner.withUserConfiguration(TestMvcConfiguration.class).run((context) -> {
AntPathRequestMatcherProvider matcherProvider = context.getBean(AntPathRequestMatcherProvider.class);
RequestMatcher requestMatcher = matcherProvider.getRequestMatcher("/example", null);
assertThat(requestMatcher).extracting("pattern").isEqualTo("/custom/example");
assertThat(requestMatcher).extracting("pattern")
.isEqualTo(PathPatternParser.defaultInstance.parse("/custom/example"));
});
}

Expand All @@ -71,7 +73,8 @@ void registersRequestMatcherForJerseyProviderIfJerseyPresentAndMvcAbsent() {
.run((context) -> {
AntPathRequestMatcherProvider matcherProvider = context.getBean(AntPathRequestMatcherProvider.class);
RequestMatcher requestMatcher = matcherProvider.getRequestMatcher("/example", null);
assertThat(requestMatcher).extracting("pattern").isEqualTo("/admin/example");
assertThat(requestMatcher).extracting("pattern")
.isEqualTo(PathPatternParser.defaultInstance.parse("/admin/example"));
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-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.
Expand All @@ -24,6 +24,7 @@
import org.springframework.boot.autoconfigure.security.StaticResourceLocation;
import org.springframework.boot.security.servlet.ApplicationContextRequestMatcher;
import org.springframework.boot.web.context.WebServerApplicationContext;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.context.WebApplicationContext;

Expand Down Expand Up @@ -76,10 +77,9 @@ protected boolean ignoreApplicationContext(WebApplicationContext applicationCont
}

@Override
@SuppressWarnings("removal")
protected void initialized(Supplier<H2ConsoleProperties> h2ConsoleProperties) {
this.delegate = new org.springframework.security.web.util.matcher.AntPathRequestMatcher(
h2ConsoleProperties.get().getPath() + "/**");
this.delegate = PathPatternRequestMatcher.withDefaults()
.matcher(h2ConsoleProperties.get().getPath() + "/**");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
import org.springframework.boot.security.servlet.ApplicationContextRequestMatcher;
import org.springframework.boot.web.context.WebServerApplicationContext;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -134,10 +135,8 @@ protected void initialized(Supplier<DispatcherServletPath> dispatcherServletPath
this.delegate = new OrRequestMatcher(getDelegateMatchers(dispatcherServletPath.get()).toList());
}

@SuppressWarnings("removal")
private Stream<RequestMatcher> getDelegateMatchers(DispatcherServletPath dispatcherServletPath) {
return getPatterns(dispatcherServletPath)
.map(org.springframework.security.web.util.matcher.AntPathRequestMatcher::new);
return getPatterns(dispatcherServletPath).map(PathPatternRequestMatcher.withDefaults()::matcher);
}

private Stream<String> getPatterns(DispatcherServletPath dispatcherServletPath) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-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.
Expand All @@ -25,6 +25,7 @@
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -99,14 +100,14 @@ private MockHttpServletRequest mockRequest(String path) {
MockServletContext servletContext = new MockServletContext();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
MockHttpServletRequest request = new MockHttpServletRequest(servletContext);
request.setPathInfo(path);
request.setRequestURI(path);
return request;
}

private String getRequestPath(HttpServletRequest request) {
String url = request.getServletPath();
if (request.getPathInfo() != null) {
url += request.getPathInfo();
if (StringUtils.hasText(request.getRequestURI())) {
url += request.getRequestURI();
}
return url;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -156,15 +157,18 @@ private MockHttpServletRequest mockRequest(String servletPath, String path) {
MockHttpServletRequest request = new MockHttpServletRequest(servletContext);
if (servletPath != null) {
request.setServletPath(servletPath);
request.setRequestURI(servletPath + path);
}
else {
request.setRequestURI(path);
}
request.setPathInfo(path);
return request;
}

private String getRequestPath(HttpServletRequest request) {
String url = request.getServletPath();
if (request.getPathInfo() != null) {
url += request.getPathInfo();
if (StringUtils.hasText(request.getRequestURI())) {
url += request.getRequestURI();
}
return url;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-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.
Expand All @@ -25,6 +25,7 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;

/**
* Spring Security configuration that allows anonymous access to the remote devtools
Expand All @@ -45,10 +46,9 @@ class RemoteDevtoolsSecurityConfiguration {
}

@Bean
@SuppressWarnings("removal")
@Order(SecurityProperties.BASIC_AUTH_ORDER - 1)
SecurityFilterChain devtoolsSecurityFilterChain(HttpSecurity http) throws Exception {
http.securityMatcher(new org.springframework.security.web.util.matcher.AntPathRequestMatcher(this.url));
http.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher(this.url));
http.authorizeHttpRequests((requests) -> requests.anyRequest().anonymous());
http.csrf(CsrfConfigurer::disable);
return http.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-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.
Expand Down Expand Up @@ -31,7 +31,7 @@
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
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.web.servlet.handler.HandlerMappingIntrospector;

import static org.springframework.security.config.Customizer.withDefaults;
Expand Down Expand Up @@ -68,9 +68,9 @@ SecurityFilterChain configure(HttpSecurity http, HandlerMappingIntrospector hand
requests.requestMatchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class))
.hasRole("ACTUATOR");
requests.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
requests.requestMatchers(new AntPathRequestMatcher("/foo")).permitAll();
requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/foo")).permitAll();
requests.requestMatchers(new MvcRequestMatcher(handlerMappingIntrospector, "/error")).permitAll();
requests.requestMatchers(new AntPathRequestMatcher("/**")).hasRole("USER");
requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/**")).hasRole("USER");
});
http.cors(withDefaults());
http.httpBasic(withDefaults());
Expand Down