Use PathPatternRequestMatcher in Web Components

This commit changes filters and resolvers that were using AntPathRequestMatcher as their
default to using PathPatternRequestMatcher.

Issue gh-16632
This commit is contained in:
Josh Cummings 2025-03-26 11:14:50 -06:00
parent 50ad378a29
commit de07b1108f
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
29 changed files with 133 additions and 113 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* 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.
@ -20,13 +20,14 @@ import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.web.authentication.AuthenticationConverter;
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;
@ -45,7 +46,8 @@ final class OidcLogoutAuthenticationConverter implements AuthenticationConverter
private final ClientRegistrationRepository clientRegistrationRepository;
private RequestMatcher requestMatcher = new AntPathRequestMatcher(DEFAULT_LOGOUT_URI, "POST");
private RequestMatcher requestMatcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.POST, DEFAULT_LOGOUT_URI);
OidcLogoutAuthenticationConverter(ClientRegistrationRepository clientRegistrationRepository) {
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");

View File

@ -36,8 +36,9 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequ
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
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.util.CollectionUtils;
import org.springframework.util.StringUtils;
@ -80,7 +81,7 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au
private final ClientRegistrationRepository clientRegistrationRepository;
private final AntPathRequestMatcher authorizationRequestMatcher;
private final RequestMatcher authorizationRequestMatcher;
private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer = (customizer) -> {
};
@ -97,8 +98,8 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty");
this.clientRegistrationRepository = clientRegistrationRepository;
this.authorizationRequestMatcher = new AntPathRequestMatcher(
authorizationRequestBaseUri + "/{" + REGISTRATION_ID_URI_VARIABLE_NAME + "}");
this.authorizationRequestMatcher = PathPatternRequestMatcher.withDefaults()
.matcher(authorizationRequestBaseUri + "/{" + REGISTRATION_ID_URI_VARIABLE_NAME + "}");
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -31,7 +31,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
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;
@ -47,8 +47,8 @@ final class BaseOpenSamlAuthenticationTokenConverter implements AuthenticationCo
private final RelyingPartyRegistrationRepository registrations;
private RequestMatcher requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher("/login/saml2/sso/{registrationId}"),
new AntPathRequestMatcher("/login/saml2/sso"));
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso"));
private Saml2AuthenticationRequestRepository<?> authenticationRequests = new HttpSessionSaml2AuthenticationRequestRepository();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* 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.
@ -16,15 +16,18 @@
package org.springframework.security.saml2.provider.service.web;
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.RequestPath;
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.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
@ -43,7 +46,25 @@ public final class DefaultRelyingPartyRegistrationResolver
private final RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
private final RequestMatcher registrationRequestMatcher = new AntPathRequestMatcher("/**/{registrationId}");
private final RequestMatcher registrationRequestMatcher = new RequestMatcher() {
@Override
public boolean matches(HttpServletRequest request) {
return matcher(request).isMatch();
}
@Override
public MatchResult matcher(HttpServletRequest request) {
RequestPath path = RequestPath.parse(request.getRequestURI(), request.getContextPath());
PathContainer contextPath = path.contextPath();
PathContainer relativePath = path.subPath(contextPath.elements().size());
int size = relativePath.elements().size();
if (size > 0) {
return RequestMatcher.MatchResult
.match(Map.of("registrationId", relativePath.elements().get(size - 1).value()));
}
return RequestMatcher.MatchResult.notMatch();
}
};
public DefaultRelyingPartyRegistrationResolver(
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -32,7 +32,7 @@ import org.springframework.security.saml2.provider.service.metadata.Saml2Metadat
import org.springframework.security.saml2.provider.service.metadata.Saml2MetadataResponseResolver;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
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.OncePerRequestFilter;
@ -146,8 +146,8 @@ public final class Saml2MetadataFilter extends OncePerRequestFilter {
private final RelyingPartyRegistrationResolver registrations;
private RequestMatcher requestMatcher = new AntPathRequestMatcher(
"/saml2/service-provider-metadata/{registrationId}");
private RequestMatcher requestMatcher = PathPatternRequestMatcher.withDefaults()
.matcher("/saml2/service-provider-metadata/{registrationId}");
private final Saml2MetadataResolver metadataResolver;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -50,8 +50,8 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.ParameterRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatchers;
@ -82,8 +82,9 @@ class BaseOpenSamlAuthenticationRequestResolver implements Saml2AuthenticationRe
private final NameIDPolicyBuilder nameIdPolicyBuilder;
private RequestMatcher requestMatcher = RequestMatchers.anyOf(
new AntPathRequestMatcher(Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI),
new AntPathQueryRequestMatcher("/saml2/authenticate", "registrationId={registrationId}"));
PathPatternRequestMatcher.withDefaults()
.matcher(Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI),
new PathPatternQueryRequestMatcher("/saml2/authenticate", "registrationId={registrationId}"));
private Clock clock = Clock.systemUTC();
@ -215,13 +216,13 @@ class BaseOpenSamlAuthenticationRequestResolver implements Saml2AuthenticationRe
return this.saml.serialize(authnRequest).serialize();
}
private static final class AntPathQueryRequestMatcher implements RequestMatcher {
private static final class PathPatternQueryRequestMatcher implements RequestMatcher {
private final RequestMatcher matcher;
AntPathQueryRequestMatcher(String path, String... params) {
PathPatternQueryRequestMatcher(String path, String... params) {
List<RequestMatcher> matchers = new ArrayList<>();
matchers.add(new AntPathRequestMatcher(path));
matchers.add(PathPatternRequestMatcher.withDefaults().matcher(path));
for (String param : params) {
String[] parts = param.split("=");
if (parts.length == 1) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* 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.
@ -35,7 +35,7 @@ import org.springframework.security.saml2.provider.service.web.Saml2Authenticati
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
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;
@ -48,7 +48,8 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/saml2/sso/{registrationId}";
private static final RequestMatcher DEFAULT_REQUEST_MATCHER = new OrRequestMatcher(
new AntPathRequestMatcher(DEFAULT_FILTER_PROCESSES_URI), new AntPathRequestMatcher("/login/saml2/sso"));
PathPatternRequestMatcher.withDefaults().matcher(DEFAULT_FILTER_PROCESSES_URI),
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso"));
private final AuthenticationConverter authenticationConverter;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -33,7 +33,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
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;
@ -54,8 +54,8 @@ final class BaseOpenSamlLogoutRequestValidatorParametersResolver
private final RelyingPartyRegistrationRepository registrations;
private RequestMatcher requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher("/logout/saml2/slo/{registrationId}"),
new AntPathRequestMatcher("/logout/saml2/slo"));
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo"));
/**
* Constructs a {@link BaseOpenSamlLogoutRequestValidatorParametersResolver}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* 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.
@ -49,7 +49,7 @@ import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.logout.CompositeLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
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.util.StringUtils;
@ -245,7 +245,8 @@ public final class Saml2LogoutRequestFilter extends OncePerRequestFilter {
private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
private RequestMatcher logoutRequestMatcher = new AntPathRequestMatcher("/logout/saml2/slo");
private RequestMatcher logoutRequestMatcher = PathPatternRequestMatcher.withDefaults()
.matcher("/logout/saml2/slo");
Saml2AssertingPartyLogoutRequestResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* 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.
@ -41,7 +41,7 @@ import org.springframework.security.saml2.provider.service.web.RelyingPartyRegis
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
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.OncePerRequestFilter;
@ -72,7 +72,7 @@ public final class Saml2LogoutResponseFilter extends OncePerRequestFilter {
private Saml2LogoutRequestRepository logoutRequestRepository = new HttpSessionLogoutRequestRepository();
private RequestMatcher logoutRequestMatcher = new AntPathRequestMatcher("/logout/saml2/slo");
private RequestMatcher logoutRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo");
public Saml2LogoutResponseFilter(RelyingPartyRegistrationRepository registrations,
Saml2LogoutResponseValidator logoutResponseValidator, LogoutSuccessHandler logoutSuccessHandler) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -34,7 +34,7 @@ import org.springframework.security.saml2.provider.service.registration.Iterable
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.web.RelyingPartyRegistrationPlaceholderResolvers;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
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;
@ -51,9 +51,9 @@ public class RequestMatcherMetadataResponseResolver implements Saml2MetadataResp
private static final String DEFAULT_METADATA_FILENAME = "saml-{registrationId}-metadata.xml";
private RequestMatcher matcher = new OrRequestMatcher(
new AntPathRequestMatcher("/saml2/service-provider-metadata/{registrationId}"),
new AntPathRequestMatcher("/saml2/metadata/{registrationId}"),
new AntPathRequestMatcher("/saml2/metadata"));
PathPatternRequestMatcher.withDefaults().matcher("/saml2/service-provider-metadata/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/saml2/metadata/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/saml2/metadata"));
private String filename = DEFAULT_METADATA_FILENAME;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* 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.
@ -33,7 +33,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
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;
@ -60,8 +60,8 @@ public final class OpenSamlAuthenticationTokenConverter implements Authenticatio
private final RelyingPartyRegistrationRepository registrations;
private RequestMatcher requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher("/login/saml2/sso/{registrationId}"),
new AntPathRequestMatcher("/login/saml2/sso"));
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso"));
private Function<HttpServletRequest, AbstractSaml2AuthenticationRequest> loader;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* 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.
@ -37,7 +37,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
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;
@ -59,8 +59,8 @@ public final class OpenSamlLogoutRequestValidatorParametersResolver
}
private RequestMatcher requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher("/logout/saml2/slo/{registrationId}"),
new AntPathRequestMatcher("/logout/saml2/slo"));
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo"));
private final OpenSamlOperations saml = new OpenSaml4Template();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* 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.
@ -35,7 +35,6 @@ import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
@ -99,21 +98,6 @@ public final class ExpressionBasedFilterInvocationSecurityMetadataSource
return new RequestVariablesExtractorEvaluationContextPostProcessor(request);
}
static class AntPathMatcherEvaluationContextPostProcessor extends AbstractVariableEvaluationContextPostProcessor {
private final AntPathRequestMatcher matcher;
AntPathMatcherEvaluationContextPostProcessor(AntPathRequestMatcher matcher) {
this.matcher = matcher;
}
@Override
Map<String, String> extractVariables(HttpServletRequest request) {
return this.matcher.matcher(request).getVariables();
}
}
static class RequestVariablesExtractorEvaluationContextPostProcessor
extends AbstractVariableEvaluationContextPostProcessor {

View File

@ -46,7 +46,7 @@ import org.springframework.security.web.authentication.session.NullAuthenticated
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,11 +395,11 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
* @param filterProcessesUrl
*/
public void setFilterProcessesUrl(String filterProcessesUrl) {
setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(filterProcessesUrl));
setRequiresAuthenticationRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(filterProcessesUrl));
}
public final void setRequiresAuthenticationRequestMatcher(RequestMatcher requestMatcher) {
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
Assert.notNull(requestMatcher, "requestMatcher cannot be null or empty");
this.requiresAuthenticationRequestMatcher = requestMatcher;
}

View File

@ -19,13 +19,15 @@ package org.springframework.security.web.authentication;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
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;
/**
@ -51,8 +53,8 @@ public class UsernamePasswordAuthenticationFilter extends AbstractAuthentication
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/login",
"POST");
private static final RequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.POST, "/login");
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;

View File

@ -29,8 +29,8 @@ import org.springframework.core.log.LogMessage;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
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.util.StringUtils;
@ -140,7 +140,7 @@ public class LogoutFilter extends GenericFilterBean {
}
public void setFilterProcessesUrl(String filterProcessesUrl) {
this.logoutRequestMatcher = new AntPathRequestMatcher(filterProcessesUrl);
this.logoutRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher(filterProcessesUrl);
}
}

View File

@ -27,13 +27,12 @@ import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.ott.GenerateOneTimeTokenRequest;
import org.springframework.security.authentication.ott.OneTimeToken;
import org.springframework.security.authentication.ott.OneTimeTokenService;
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.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
/**
* Filter that process a One-Time Token generation request.
*
@ -49,7 +48,8 @@ public final class GenerateOneTimeTokenFilter extends OncePerRequestFilter {
private final OneTimeTokenGenerationSuccessHandler tokenGenerationSuccessHandler;
private RequestMatcher requestMatcher = antMatcher(HttpMethod.POST, DEFAULT_GENERATE_URL);
private RequestMatcher requestMatcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.POST, DEFAULT_GENERATE_URL);
private GenerateOneTimeTokenRequestResolver requestResolver = new DefaultGenerateOneTimeTokenRequestResolver();

View File

@ -16,8 +16,9 @@
package org.springframework.security.web.authentication.ott;
import org.springframework.http.HttpMethod;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
/**
* Filter that processes a one-time token for log in.
@ -33,7 +34,7 @@ public final class OneTimeTokenAuthenticationFilter extends AbstractAuthenticati
public static final String DEFAULT_LOGIN_PROCESSING_URL = "/login/ott";
public OneTimeTokenAuthenticationFilter() {
super(new AntPathRequestMatcher(DEFAULT_LOGIN_PROCESSING_URL, "POST"));
super(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, DEFAULT_LOGIN_PROCESSING_URL));
setAuthenticationConverter(new OneTimeTokenAuthenticationConverter());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -27,7 +27,8 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.log.LogMessage;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.http.HttpMethod;
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.OncePerRequestFilter;
@ -40,7 +41,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
*/
public class DefaultLogoutPageGeneratingFilter extends OncePerRequestFilter {
private RequestMatcher matcher = new AntPathRequestMatcher("/logout", "GET");
private RequestMatcher matcher = PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/logout");
private Function<HttpServletRequest, Map<String, String>> resolveHiddenInputs = (request) -> Collections.emptyMap();

View File

@ -28,8 +28,9 @@ import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationFilter;
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.util.StringUtils;
@ -46,7 +47,8 @@ public final class DefaultOneTimeTokenSubmitPageGeneratingFilter extends OncePer
public static final String DEFAULT_SUBMIT_PAGE_URL = "/login/ott";
private RequestMatcher requestMatcher = new AntPathRequestMatcher(DEFAULT_SUBMIT_PAGE_URL, "GET");
private RequestMatcher requestMatcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.GET, DEFAULT_SUBMIT_PAGE_URL);
private Function<HttpServletRequest, Map<String, String>> resolveHiddenInputs = (request) -> Collections.emptyMap();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -28,7 +28,7 @@ import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
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;
@ -89,7 +89,8 @@ public final class DefaultResourcesFilter extends GenericFilterBean {
* @return -
*/
public static DefaultResourcesFilter css() {
return new DefaultResourcesFilter(AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/default-ui.css"),
return new DefaultResourcesFilter(
PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/default-ui.css"),
new ClassPathResource("org/springframework/security/default-ui.css"),
new MediaType("text", "css", StandardCharsets.UTF_8));
}
@ -106,7 +107,8 @@ public final class DefaultResourcesFilter extends GenericFilterBean {
* @return -
*/
public static DefaultResourcesFilter webauthn() {
return new DefaultResourcesFilter(AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/login/webauthn.js"),
return new DefaultResourcesFilter(
PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/login/webauthn.js"),
new ClassPathResource("org/springframework/security/spring-security-webauthn.js"),
new MediaType("text", "javascript", StandardCharsets.UTF_8));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -33,6 +33,7 @@ import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
@ -41,8 +42,6 @@ import org.springframework.security.web.webauthn.management.WebAuthnRelyingParty
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
/**
* A {@link jakarta.servlet.Filter} that renders the
* {@link PublicKeyCredentialRequestOptions} in order to <a href=
@ -54,7 +53,8 @@ import static org.springframework.security.web.util.matcher.AntPathRequestMatche
*/
public class PublicKeyCredentialRequestOptionsFilter extends OncePerRequestFilter {
private RequestMatcher matcher = antMatcher(HttpMethod.POST, "/webauthn/authenticate/options");
private RequestMatcher matcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.POST, "/webauthn/authenticate/options");
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -37,6 +37,7 @@ import org.springframework.security.web.authentication.AuthenticationEntryPointF
import org.springframework.security.web.authentication.HttpMessageConverterAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
@ -44,8 +45,6 @@ import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
import org.springframework.util.Assert;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
/**
* Authenticates {@code PublicKeyCredential<AuthenticatorAssertionResponse>} that is
* parsed from the body of the {@link HttpServletRequest} using the
@ -78,7 +77,7 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi
private PublicKeyCredentialRequestOptionsRepository requestOptionsRepository = new HttpSessionPublicKeyCredentialRequestOptionsRepository();
public WebAuthnAuthenticationFilter() {
super(antMatcher(HttpMethod.POST, "/login/webauthn"));
super(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/login/webauthn"));
setSecurityContextRepository(new HttpSessionSecurityContextRepository());
setAuthenticationFailureHandler(
new AuthenticationEntryPointFailureHandler(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -34,7 +34,7 @@ import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.web.csrf.CsrfToken;
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.security.web.webauthn.api.CredentialRecord;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
@ -52,7 +52,8 @@ import org.springframework.web.filter.OncePerRequestFilter;
*/
public class DefaultWebAuthnRegistrationPageGeneratingFilter extends OncePerRequestFilter {
private RequestMatcher matcher = AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/webauthn/register");
private RequestMatcher matcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.GET, "/webauthn/register");
private final PublicKeyCredentialUserEntityRepository userEntities;

View File

@ -38,6 +38,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.jackson.WebauthnJackson2Module;
@ -46,8 +47,6 @@ import org.springframework.security.web.webauthn.management.WebAuthnRelyingParty
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
/**
* A {@link jakarta.servlet.Filter} that renders the
* {@link PublicKeyCredentialCreationOptions} for <a href=
@ -63,7 +62,8 @@ public class PublicKeyCredentialCreationOptionsFilter extends OncePerRequestFilt
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
.getContextHolderStrategy();
private RequestMatcher matcher = antMatcher(HttpMethod.POST, "/webauthn/register/options");
private RequestMatcher matcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.POST, "/webauthn/register/options");
private AuthorizationManager<HttpServletRequest> authorization = AuthenticatedAuthorizationManager.authenticated();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -34,6 +34,7 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.Bytes;
import org.springframework.security.web.webauthn.api.CredentialRecord;
@ -46,8 +47,6 @@ import org.springframework.security.web.webauthn.management.WebAuthnRelyingParty
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
/**
* Authenticates {@code PublicKeyCredential<AuthenticatorAssertionResponse>} that is
* parsed from the body of the {@link HttpServletRequest} using the
@ -93,9 +92,11 @@ public class WebAuthnRegistrationFilter extends OncePerRequestFilter {
private PublicKeyCredentialCreationOptionsRepository creationOptionsRepository = new HttpSessionPublicKeyCredentialCreationOptionsRepository();
private RequestMatcher registerCredentialMatcher = antMatcher(HttpMethod.POST, DEFAULT_REGISTER_CREDENTIAL_URL);
private RequestMatcher registerCredentialMatcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.POST, DEFAULT_REGISTER_CREDENTIAL_URL);
private RequestMatcher removeCredentialMatcher = antMatcher(HttpMethod.DELETE, "/webauthn/register/{id}");
private RequestMatcher removeCredentialMatcher = PathPatternRequestMatcher.withDefaults()
.matcher(HttpMethod.DELETE, "/webauthn/register/{id}");
public WebAuthnRegistrationFilter(UserCredentialRepository userCredentials,
WebAuthnRelyingPartyOperations rpOptions) {

View File

@ -273,7 +273,7 @@ public class AbstractAuthenticationProcessingFilterTests {
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

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
@ -59,7 +59,7 @@ public class DefaultResourcesFilterTests {
@Test
void toStringPrintsPathAndResource() {
assertThat(this.cssFilter.toString()).isEqualTo(
"DefaultResourcesFilter [matcher=Ant [pattern='/default-ui.css', GET], resource=org/springframework/security/default-ui.css]");
"DefaultResourcesFilter [matcher=PathPattern [GET /default-ui.css], resource=org/springframework/security/default-ui.css]");
}
}
@ -89,7 +89,7 @@ public class DefaultResourcesFilterTests {
@Test
void toStringPrintsPathAndResource() {
assertThat(this.webauthnFilter.toString()).isEqualTo(
"DefaultResourcesFilter [matcher=Ant [pattern='/login/webauthn.js', GET], resource=org/springframework/security/spring-security-webauthn.js]");
"DefaultResourcesFilter [matcher=PathPattern [GET /login/webauthn.js], resource=org/springframework/security/spring-security-webauthn.js]");
}
}