Skip to content

Commit e071a9d

Browse files
committed
Polish Opt-in
1 parent aadb000 commit e071a9d

23 files changed

+565
-67
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
import org.springframework.security.config.annotation.web.ServletRegistrationsSupport.RegistrationMapping;
4444
import org.springframework.security.config.annotation.web.configurers.AbstractConfigAttributeRequestMatcherRegistry;
4545
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
46+
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
4647
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
4748
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
4849
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
49-
import org.springframework.security.web.util.matcher.MethodPathRequestMatcherFactory;
5050
import org.springframework.security.web.util.matcher.OrRequestMatcher;
5151
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
5252
import org.springframework.security.web.util.matcher.RequestMatcher;
@@ -332,8 +332,10 @@ public C requestMatchers(HttpMethod method) {
332332
protected abstract C chainRequestMatchers(List<RequestMatcher> requestMatchers);
333333

334334
private MethodPathRequestMatcherFactory getRequestMatcherFactory() {
335-
return this.context.getBeanProvider(MethodPathRequestMatcherFactory.class)
336-
.getIfUnique(DefaultMethodPathRequestMatcherFactory::new);
335+
PathPatternRequestMatcher.Builder builder = this.context
336+
.getBeanProvider(PathPatternRequestMatcher.Builder.class)
337+
.getIfUnique();
338+
return (builder != null) ? builder::matcher : new DefaultMethodPathRequestMatcherFactory();
337339
}
338340

339341
/**
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.web;
18+
19+
import org.springframework.context.ApplicationContext;
20+
import org.springframework.http.HttpMethod;
21+
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
22+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
23+
import org.springframework.security.web.util.matcher.RequestMatcher;
24+
25+
interface MethodPathRequestMatcherFactory {
26+
27+
default RequestMatcher matcher(String path) {
28+
return matcher(null, path);
29+
}
30+
31+
RequestMatcher matcher(HttpMethod method, String path);
32+
33+
static MethodPathRequestMatcherFactory fromApplicationContext(ApplicationContext context) {
34+
PathPatternRequestMatcher.Builder builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
35+
.getIfUnique();
36+
return (builder != null) ? builder::matcher : AntPathRequestMatcher::antMatcher;
37+
}
38+
39+
}

config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -90,10 +90,10 @@
9090
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
9191
import org.springframework.security.web.context.SecurityContextRepository;
9292
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
93+
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
9394
import org.springframework.security.web.session.HttpSessionEventPublisher;
9495
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
9596
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
96-
import org.springframework.security.web.util.matcher.MethodPathRequestMatcherFactory;
9797
import org.springframework.security.web.util.matcher.OrRequestMatcher;
9898
import org.springframework.security.web.util.matcher.RequestMatcher;
9999
import org.springframework.util.Assert;
@@ -3686,9 +3686,11 @@ public HttpSecurity securityMatcher(RequestMatcher requestMatcher) {
36863686
*/
36873687
public HttpSecurity securityMatcher(String... patterns) {
36883688
List<RequestMatcher> matchers = new ArrayList<>();
3689-
MethodPathRequestMatcherFactory factory = getSharedObject(ApplicationContext.class)
3690-
.getBeanProvider(MethodPathRequestMatcherFactory.class)
3691-
.getIfUnique(() -> (method, pattern) -> mvcPresent ? createMvcMatcher(pattern) : createAntMatcher(pattern));
3689+
PathPatternRequestMatcher.Builder builder = getSharedObject(ApplicationContext.class)
3690+
.getBeanProvider(PathPatternRequestMatcher.Builder.class)
3691+
.getIfUnique();
3692+
MethodPathRequestMatcherFactory factory = (builder != null) ? builder::matcher
3693+
: (method, pattern) -> mvcPresent ? createMvcMatcher(pattern) : createAntMatcher(pattern);
36923694
for (String pattern : patterns) {
36933695
matchers.add(factory.matcher(pattern));
36943696
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.web.builders;
18+
19+
import org.springframework.context.ApplicationContext;
20+
import org.springframework.http.HttpMethod;
21+
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
22+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
23+
import org.springframework.security.web.util.matcher.RequestMatcher;
24+
25+
interface MethodPathRequestMatcherFactory {
26+
27+
default RequestMatcher matcher(String path) {
28+
return matcher(null, path);
29+
}
30+
31+
RequestMatcher matcher(HttpMethod method, String path);
32+
33+
static MethodPathRequestMatcherFactory fromApplicationContext(ApplicationContext context) {
34+
PathPatternRequestMatcher.Builder builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
35+
.getIfUnique();
36+
return (builder != null) ? builder::matcher : AntPathRequestMatcher::antMatcher;
37+
}
38+
39+
}

config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
2929
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
3030
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
31-
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
32-
import org.springframework.security.web.util.matcher.MethodPathRequestMatcherFactory;
3331
import org.springframework.security.web.util.matcher.RequestMatcher;
3432

3533
/**
@@ -275,9 +273,8 @@ private void initDefaultLoginFilter(H http) {
275273
}
276274

277275
private MethodPathRequestMatcherFactory getRequestMatcherFactory() {
278-
return getBuilder().getSharedObject(ApplicationContext.class)
279-
.getBeanProvider(MethodPathRequestMatcherFactory.class)
280-
.getIfUnique(() -> AntPathRequestMatcher::antMatcher);
276+
return MethodPathRequestMatcherFactory
277+
.fromApplicationContext(getBuilder().getSharedObject(ApplicationContext.class));
281278
}
282279

283280
}

config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@
3939
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
4040
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
4141
import org.springframework.security.web.context.SecurityContextRepository;
42-
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
43-
import org.springframework.security.web.util.matcher.MethodPathRequestMatcherFactory;
4442
import org.springframework.security.web.util.matcher.OrRequestMatcher;
4543
import org.springframework.security.web.util.matcher.RequestMatcher;
4644
import org.springframework.util.Assert;
@@ -375,9 +373,8 @@ private RequestMatcher createLogoutRequestMatcher(String httpMethod) {
375373
}
376374

377375
private MethodPathRequestMatcherFactory getRequestMatcherFactory() {
378-
return getBuilder().getSharedObject(ApplicationContext.class)
379-
.getBeanProvider(MethodPathRequestMatcherFactory.class)
380-
.getIfUnique(() -> AntPathRequestMatcher::antMatcher);
376+
return MethodPathRequestMatcherFactory
377+
.fromApplicationContext(getBuilder().getSharedObject(ApplicationContext.class));
381378
}
382379

383380
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.web.configurers;
18+
19+
import org.springframework.context.ApplicationContext;
20+
import org.springframework.http.HttpMethod;
21+
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
22+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
23+
import org.springframework.security.web.util.matcher.RequestMatcher;
24+
25+
interface MethodPathRequestMatcherFactory {
26+
27+
default RequestMatcher matcher(String path) {
28+
return matcher(null, path);
29+
}
30+
31+
RequestMatcher matcher(HttpMethod method, String path);
32+
33+
static MethodPathRequestMatcherFactory fromApplicationContext(ApplicationContext context) {
34+
PathPatternRequestMatcher.Builder builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
35+
.getIfUnique();
36+
return (builder != null) ? builder::matcher : AntPathRequestMatcher::antMatcher;
37+
}
38+
39+
}

config/src/main/java/org/springframework/security/config/annotation/web/configurers/PasswordManagementConfigurer.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
2121
import org.springframework.security.web.RequestMatcherRedirectFilter;
2222
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
23-
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
24-
import org.springframework.security.web.util.matcher.MethodPathRequestMatcherFactory;
2523
import org.springframework.util.Assert;
2624

2725
/**
@@ -62,9 +60,8 @@ public void configure(B http) throws Exception {
6260
}
6361

6462
private MethodPathRequestMatcherFactory getRequestMatcherFactory() {
65-
return getBuilder().getSharedObject(ApplicationContext.class)
66-
.getBeanProvider(MethodPathRequestMatcherFactory.class)
67-
.getIfUnique(() -> AntPathRequestMatcher::antMatcher);
63+
return MethodPathRequestMatcherFactory
64+
.fromApplicationContext(getBuilder().getSharedObject(ApplicationContext.class));
6865
}
6966

7067
}

config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,31 @@
1919
import java.util.ArrayList;
2020
import java.util.Collections;
2121
import java.util.List;
22+
import java.util.regex.Pattern;
23+
24+
import jakarta.servlet.http.HttpServletRequest;
2225

2326
import org.springframework.context.ApplicationContext;
2427
import org.springframework.http.HttpMethod;
2528
import org.springframework.http.MediaType;
29+
import org.springframework.http.server.PathContainer;
30+
import org.springframework.http.server.RequestPath;
2631
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
2732
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
2833
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
2934
import org.springframework.security.web.savedrequest.NullRequestCache;
3035
import org.springframework.security.web.savedrequest.RequestCache;
3136
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
37+
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
3238
import org.springframework.security.web.util.matcher.AndRequestMatcher;
3339
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
3440
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
35-
import org.springframework.security.web.util.matcher.MethodPathRequestMatcherFactory;
3641
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
3742
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
3843
import org.springframework.security.web.util.matcher.RequestMatcher;
3944
import org.springframework.web.accept.ContentNegotiationStrategy;
4045
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
46+
import org.springframework.web.util.ServletRequestPathUtils;
4147

4248
/**
4349
* Adds request cache for Spring Security. Specifically this ensures that requests that
@@ -142,7 +148,7 @@ private <T> T getBeanOrNull(Class<T> type) {
142148

143149
@SuppressWarnings("unchecked")
144150
private RequestMatcher createDefaultSavedRequestMatcher(H http) {
145-
RequestMatcher notFavIcon = new NegatedRequestMatcher(getRequestMatcherFactory().matcher("/**/favicon.*"));
151+
RequestMatcher notFavIcon = new NegatedRequestMatcher(getFaviconRequestMatcher());
146152
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
147153
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
148154
boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
@@ -169,10 +175,39 @@ private RequestMatcher notMatchingMediaType(H http, MediaType mediaType) {
169175
return new NegatedRequestMatcher(mediaRequest);
170176
}
171177

178+
private RequestMatcher getFaviconRequestMatcher() {
179+
PathPatternRequestMatcher.Builder builder = getBuilder().getSharedObject(ApplicationContext.class)
180+
.getBeanProvider(PathPatternRequestMatcher.Builder.class)
181+
.getIfUnique();
182+
if (builder == null) {
183+
return new AntPathRequestMatcher("/**/favicon.*");
184+
}
185+
else {
186+
return new FilenameRequestMatcher(Pattern.compile("favicon.*"));
187+
}
188+
}
189+
172190
private MethodPathRequestMatcherFactory getRequestMatcherFactory() {
173-
return getBuilder().getSharedObject(ApplicationContext.class)
174-
.getBeanProvider(MethodPathRequestMatcherFactory.class)
175-
.getIfUnique(() -> AntPathRequestMatcher::antMatcher);
191+
ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class);
192+
return MethodPathRequestMatcherFactory.fromApplicationContext(context);
193+
}
194+
195+
private static final class FilenameRequestMatcher implements RequestMatcher {
196+
197+
private final Pattern pattern;
198+
199+
FilenameRequestMatcher(Pattern pattern) {
200+
this.pattern = pattern;
201+
}
202+
203+
@Override
204+
public boolean matches(HttpServletRequest request) {
205+
RequestPath path = ServletRequestPathUtils.getParsedRequestPath(request);
206+
List<PathContainer.Element> elements = path.elements();
207+
String file = elements.get(elements.size() - 1).value();
208+
return this.pattern.matcher(file).matches();
209+
}
210+
176211
}
177212

178213
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
18+
19+
import org.springframework.context.ApplicationContext;
20+
import org.springframework.http.HttpMethod;
21+
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
22+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
23+
import org.springframework.security.web.util.matcher.RequestMatcher;
24+
25+
interface MethodPathRequestMatcherFactory {
26+
27+
default RequestMatcher matcher(String path) {
28+
return matcher(null, path);
29+
}
30+
31+
RequestMatcher matcher(HttpMethod method, String path);
32+
33+
static MethodPathRequestMatcherFactory fromApplicationContext(ApplicationContext context) {
34+
PathPatternRequestMatcher.Builder builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
35+
.getIfUnique();
36+
return (builder != null) ? builder::matcher : AntPathRequestMatcher::antMatcher;
37+
}
38+
39+
}

0 commit comments

Comments
 (0)