Use PathPatternRequestMatcher in saml2

Issue gh-16887
This commit is contained in:
Josh Cummings 2025-07-02 17:48:43 -06:00
parent 558b7e0b47
commit 7da352129c
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
16 changed files with 57 additions and 56 deletions

View File

@ -29,7 +29,6 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.Customizer; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
@ -237,7 +236,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
this.authenticationRequestParams = new String[parts.length - 1]; this.authenticationRequestParams = new String[parts.length - 1];
System.arraycopy(parts, 1, this.authenticationRequestParams, 0, parts.length - 1); System.arraycopy(parts, 1, this.authenticationRequestParams, 0, parts.length - 1);
this.authenticationRequestMatcher = new PathQueryRequestMatcher( this.authenticationRequestMatcher = new PathQueryRequestMatcher(
RequestMatcherFactory.matcher(this.authenticationRequestUri), this.authenticationRequestParams); getRequestMatcherBuilder().matcher(this.authenticationRequestUri), this.authenticationRequestParams);
return this; return this;
} }
@ -254,13 +253,13 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
@Override @Override
public Saml2LoginConfigurer<B> loginProcessingUrl(String loginProcessingUrl) { public Saml2LoginConfigurer<B> loginProcessingUrl(String loginProcessingUrl) {
Assert.hasText(loginProcessingUrl, "loginProcessingUrl cannot be empty"); Assert.hasText(loginProcessingUrl, "loginProcessingUrl cannot be empty");
this.loginProcessingUrl = RequestMatcherFactory.matcher(loginProcessingUrl); this.loginProcessingUrl = getRequestMatcherBuilder().matcher(loginProcessingUrl);
return this; return this;
} }
@Override @Override
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) { protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
return RequestMatcherFactory.matcher(loginProcessingUrl); return getRequestMatcherBuilder().matcher(loginProcessingUrl);
} }
/** /**
@ -338,8 +337,8 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
} }
private AuthenticationEntryPoint getLoginEntryPoint(B http, String providerLoginPage) { private AuthenticationEntryPoint getLoginEntryPoint(B http, String providerLoginPage) {
RequestMatcher loginPageMatcher = RequestMatcherFactory.matcher(this.getLoginPage()); RequestMatcher loginPageMatcher = getRequestMatcherBuilder().matcher(this.getLoginPage());
RequestMatcher faviconMatcher = RequestMatcherFactory.matcher("/favicon.ico"); RequestMatcher faviconMatcher = getRequestMatcherBuilder().matcher("/favicon.ico");
RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(http); RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(http);
RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher( RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher(
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
@ -393,9 +392,9 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
private RequestMatcher getAuthenticationRequestMatcher() { private RequestMatcher getAuthenticationRequestMatcher() {
if (this.authenticationRequestMatcher == null) { if (this.authenticationRequestMatcher == null) {
this.authenticationRequestMatcher = RequestMatchers.anyOf( this.authenticationRequestMatcher = RequestMatchers.anyOf(
RequestMatcherFactory getRequestMatcherBuilder()
.matcher(Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI), .matcher(Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI),
new PathQueryRequestMatcher(RequestMatcherFactory.matcher(this.authenticationRequestUri), new PathQueryRequestMatcher(getRequestMatcherBuilder().matcher(this.authenticationRequestUri),
this.authenticationRequestParams)); this.authenticationRequestParams));
} }
return this.authenticationRequestMatcher; return this.authenticationRequestMatcher;
@ -404,8 +403,8 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
private RequestMatcher getLoginProcessingEndpoint() { private RequestMatcher getLoginProcessingEndpoint() {
if (this.loginProcessingUrl == null) { if (this.loginProcessingUrl == null) {
this.loginProcessingUrl = RequestMatchers.anyOf( this.loginProcessingUrl = RequestMatchers.anyOf(
RequestMatcherFactory.matcher(Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI), getRequestMatcherBuilder().matcher(Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI),
RequestMatcherFactory.matcher("/login/saml2/sso")); getRequestMatcherBuilder().matcher("/login/saml2/sso"));
} }
return this.loginProcessingUrl; return this.loginProcessingUrl;

View File

@ -27,7 +27,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer; import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
@ -279,19 +278,19 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
} }
private RequestMatcher createLogoutMatcher() { private RequestMatcher createLogoutMatcher() {
RequestMatcher logout = RequestMatcherFactory.matcher(HttpMethod.POST, this.logoutUrl); RequestMatcher logout = getRequestMatcherBuilder().matcher(HttpMethod.POST, this.logoutUrl);
RequestMatcher saml2 = new Saml2RequestMatcher(getSecurityContextHolderStrategy()); RequestMatcher saml2 = new Saml2RequestMatcher(getSecurityContextHolderStrategy());
return new AndRequestMatcher(logout, saml2); return new AndRequestMatcher(logout, saml2);
} }
private RequestMatcher createLogoutRequestMatcher() { private RequestMatcher createLogoutRequestMatcher() {
RequestMatcher logout = RequestMatcherFactory.matcher(this.logoutRequestConfigurer.logoutUrl); RequestMatcher logout = getRequestMatcherBuilder().matcher(this.logoutRequestConfigurer.logoutUrl);
RequestMatcher samlRequest = new ParameterRequestMatcher("SAMLRequest"); RequestMatcher samlRequest = new ParameterRequestMatcher("SAMLRequest");
return new AndRequestMatcher(logout, samlRequest); return new AndRequestMatcher(logout, samlRequest);
} }
private RequestMatcher createLogoutResponseMatcher() { private RequestMatcher createLogoutResponseMatcher() {
RequestMatcher logout = RequestMatcherFactory.matcher(this.logoutResponseConfigurer.logoutUrl); RequestMatcher logout = getRequestMatcherBuilder().matcher(this.logoutResponseConfigurer.logoutUrl);
RequestMatcher samlResponse = new ParameterRequestMatcher("SAMLResponse"); RequestMatcher samlResponse = new ParameterRequestMatcher("SAMLResponse");
return new AndRequestMatcher(logout, samlResponse); return new AndRequestMatcher(logout, samlResponse);
} }

View File

@ -22,7 +22,6 @@ import org.opensaml.core.Version;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.saml2.provider.service.metadata.OpenSaml4MetadataResolver; import org.springframework.security.saml2.provider.service.metadata.OpenSaml4MetadataResolver;
@ -111,12 +110,12 @@ public class Saml2MetadataConfigurer<H extends HttpSecurityBuilder<H>>
if (USE_OPENSAML_5) { if (USE_OPENSAML_5) {
RequestMatcherMetadataResponseResolver metadata = new RequestMatcherMetadataResponseResolver( RequestMatcherMetadataResponseResolver metadata = new RequestMatcherMetadataResponseResolver(
registrations, new OpenSaml5MetadataResolver()); registrations, new OpenSaml5MetadataResolver());
metadata.setRequestMatcher(RequestMatcherFactory.matcher(metadataUrl)); metadata.setRequestMatcher(getRequestMatcherBuilder().matcher(metadataUrl));
return metadata; return metadata;
} }
RequestMatcherMetadataResponseResolver metadata = new RequestMatcherMetadataResponseResolver(registrations, RequestMatcherMetadataResponseResolver metadata = new RequestMatcherMetadataResponseResolver(registrations,
new OpenSaml4MetadataResolver()); new OpenSaml4MetadataResolver());
metadata.setRequestMatcher(RequestMatcherFactory.matcher(metadataUrl)); metadata.setRequestMatcher(getRequestMatcherBuilder().matcher(metadataUrl));
return metadata; return metadata;
}; };
return this; return this;

View File

@ -38,6 +38,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockHttpSession;
@ -77,7 +78,6 @@ import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.RequestPostProcessor; import org.springframework.test.web.servlet.request.RequestPostProcessor;
@ -97,6 +97,7 @@ import static org.mockito.Mockito.spy;
import static org.springframework.security.config.Customizer.withDefaults; import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; 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.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@ -620,7 +621,7 @@ public class Saml2LogoutConfigurerTests {
.saml2Logout((saml2) -> saml2.addObjectPostProcessor(new ObjectPostProcessor<LogoutFilter>() { .saml2Logout((saml2) -> saml2.addObjectPostProcessor(new ObjectPostProcessor<LogoutFilter>() {
@Override @Override
public <O extends LogoutFilter> O postProcess(O filter) { public <O extends LogoutFilter> O postProcess(O filter) {
filter.setLogoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")); filter.setLogoutRequestMatcher(pathPattern(HttpMethod.GET, "/logout"));
return filter; return filter;
} }
})); }));

View File

@ -30,11 +30,12 @@ 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.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
final class BaseOpenSamlAuthenticationTokenConverter implements AuthenticationConverter { final class BaseOpenSamlAuthenticationTokenConverter implements AuthenticationConverter {
static { static {
@ -45,9 +46,8 @@ final class BaseOpenSamlAuthenticationTokenConverter implements AuthenticationCo
private final RelyingPartyRegistrationRepository registrations; private final RelyingPartyRegistrationRepository registrations;
private RequestMatcher requestMatcher = new OrRequestMatcher( private RequestMatcher requestMatcher = new OrRequestMatcher(pathPattern("/login/saml2/sso/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso/{registrationId}"), pathPattern("/login/saml2/sso"));
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso"));
private Saml2AuthenticationRequestRepository<?> authenticationRequests = new HttpSessionSaml2AuthenticationRequestRepository(); private Saml2AuthenticationRequestRepository<?> authenticationRequests = new HttpSessionSaml2AuthenticationRequestRepository();

View File

@ -57,6 +57,8 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatchers; import org.springframework.security.web.util.matcher.RequestMatchers;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* For internal use only. Intended for consolidating common behavior related to minting a * For internal use only. Intended for consolidating common behavior related to minting a
* SAML 2.0 Authn Request. * SAML 2.0 Authn Request.
@ -222,7 +224,7 @@ class BaseOpenSamlAuthenticationRequestResolver implements Saml2AuthenticationRe
PathPatternQueryRequestMatcher(String path, String... params) { PathPatternQueryRequestMatcher(String path, String... params) {
List<RequestMatcher> matchers = new ArrayList<>(); List<RequestMatcher> matchers = new ArrayList<>();
matchers.add(PathPatternRequestMatcher.withDefaults().matcher(path)); matchers.add(pathPattern(path));
for (String param : params) { for (String param : params) {
String[] parts = param.split("="); String[] parts = param.split("=");
if (parts.length == 1) { if (parts.length == 1) {

View File

@ -34,11 +34,12 @@ import org.springframework.security.saml2.provider.service.web.Saml2Authenticati
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy; import org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* @since 5.2 * @since 5.2
*/ */
@ -47,8 +48,7 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/saml2/sso/{registrationId}"; public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/saml2/sso/{registrationId}";
private static final RequestMatcher DEFAULT_REQUEST_MATCHER = new OrRequestMatcher( private static final RequestMatcher DEFAULT_REQUEST_MATCHER = new OrRequestMatcher(
PathPatternRequestMatcher.withDefaults().matcher(DEFAULT_FILTER_PROCESSES_URI), pathPattern(DEFAULT_FILTER_PROCESSES_URI), pathPattern("/login/saml2/sso"));
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso"));
private final AuthenticationConverter authenticationConverter; private final AuthenticationConverter authenticationConverter;
@ -64,7 +64,7 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
*/ */
public Saml2WebSsoAuthenticationFilter(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { public Saml2WebSsoAuthenticationFilter(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) {
this(relyingPartyRegistrationRepository, DEFAULT_FILTER_PROCESSES_URI); this(relyingPartyRegistrationRepository, DEFAULT_FILTER_PROCESSES_URI);
RequestMatcher processUri = PathPatternRequestMatcher.withDefaults().matcher(DEFAULT_FILTER_PROCESSES_URI); RequestMatcher processUri = pathPattern(DEFAULT_FILTER_PROCESSES_URI);
setRequiresAuthenticationRequestMatcher(processUri); setRequiresAuthenticationRequestMatcher(processUri);
} }

View File

@ -33,11 +33,12 @@ 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.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* An OpenSAML-based implementation of * An OpenSAML-based implementation of
* {@link Saml2LogoutRequestValidatorParametersResolver} * {@link Saml2LogoutRequestValidatorParametersResolver}
@ -53,9 +54,8 @@ final class BaseOpenSamlLogoutRequestValidatorParametersResolver
private final RelyingPartyRegistrationRepository registrations; private final RelyingPartyRegistrationRepository registrations;
private RequestMatcher requestMatcher = new OrRequestMatcher( private RequestMatcher requestMatcher = new OrRequestMatcher(pathPattern("/logout/saml2/slo/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo/{registrationId}"), pathPattern("/logout/saml2/slo"));
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo"));
/** /**
* Constructs a {@link BaseOpenSamlLogoutRequestValidatorParametersResolver} * Constructs a {@link BaseOpenSamlLogoutRequestValidatorParametersResolver}

View File

@ -41,11 +41,12 @@ 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.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* A filter for handling a &lt;saml2:LogoutResponse&gt; sent from the asserting party. A * A filter for handling a &lt;saml2:LogoutResponse&gt; sent from the asserting party. A
* &lt;saml2:LogoutResponse&gt; is sent in response to a &lt;saml2:LogoutRequest&gt; * &lt;saml2:LogoutResponse&gt; is sent in response to a &lt;saml2:LogoutRequest&gt;
@ -72,7 +73,7 @@ public final class Saml2LogoutResponseFilter extends OncePerRequestFilter {
private Saml2LogoutRequestRepository logoutRequestRepository = new HttpSessionLogoutRequestRepository(); private Saml2LogoutRequestRepository logoutRequestRepository = new HttpSessionLogoutRequestRepository();
private RequestMatcher logoutRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo"); private RequestMatcher logoutRequestMatcher = pathPattern("/logout/saml2/slo");
public Saml2LogoutResponseFilter(RelyingPartyRegistrationRepository registrations, public Saml2LogoutResponseFilter(RelyingPartyRegistrationRepository registrations,
Saml2LogoutResponseValidator logoutResponseValidator, LogoutSuccessHandler logoutSuccessHandler) { Saml2LogoutResponseValidator logoutResponseValidator, LogoutSuccessHandler logoutSuccessHandler) {

View File

@ -34,11 +34,12 @@ 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.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* An implementation of {@link Saml2MetadataResponseResolver} that identifies which * An implementation of {@link Saml2MetadataResponseResolver} that identifies which
* {@link RelyingPartyRegistration}s to use with a {@link RequestMatcher} * {@link RelyingPartyRegistration}s to use with a {@link RequestMatcher}
@ -51,9 +52,8 @@ public class RequestMatcherMetadataResponseResolver implements Saml2MetadataResp
private static final String DEFAULT_METADATA_FILENAME = "saml-{registrationId}-metadata.xml"; private static final String DEFAULT_METADATA_FILENAME = "saml-{registrationId}-metadata.xml";
private RequestMatcher matcher = new OrRequestMatcher( private RequestMatcher matcher = new OrRequestMatcher(
PathPatternRequestMatcher.withDefaults().matcher("/saml2/service-provider-metadata/{registrationId}"), pathPattern("/saml2/service-provider-metadata/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/saml2/metadata/{registrationId}"), pathPattern("/saml2/metadata/{registrationId}"), pathPattern("/saml2/metadata"));
PathPatternRequestMatcher.withDefaults().matcher("/saml2/metadata"));
private String filename = DEFAULT_METADATA_FILENAME; private String filename = DEFAULT_METADATA_FILENAME;

View File

@ -32,11 +32,12 @@ 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.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers.UriResolver;
import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* An {@link AuthenticationConverter} that generates a {@link Saml2AuthenticationToken} * An {@link AuthenticationConverter} that generates a {@link Saml2AuthenticationToken}
* appropriate for authenticated a SAML 2.0 Assertion against an * appropriate for authenticated a SAML 2.0 Assertion against an
@ -58,9 +59,8 @@ public final class OpenSamlAuthenticationTokenConverter implements Authenticatio
private final RelyingPartyRegistrationRepository registrations; private final RelyingPartyRegistrationRepository registrations;
private RequestMatcher requestMatcher = new OrRequestMatcher( private RequestMatcher requestMatcher = new OrRequestMatcher(pathPattern("/login/saml2/sso/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso/{registrationId}"), pathPattern("/login/saml2/sso"));
PathPatternRequestMatcher.withDefaults().matcher("/login/saml2/sso"));
private Function<HttpServletRequest, AbstractSaml2AuthenticationRequest> loader; private Function<HttpServletRequest, AbstractSaml2AuthenticationRequest> loader;

View File

@ -36,11 +36,12 @@ 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.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationPlaceholderResolvers;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* An OpenSAML-based implementation of * An OpenSAML-based implementation of
* {@link Saml2LogoutRequestValidatorParametersResolver} * {@link Saml2LogoutRequestValidatorParametersResolver}
@ -57,9 +58,8 @@ public final class OpenSamlLogoutRequestValidatorParametersResolver
OpenSamlInitializationService.initialize(); OpenSamlInitializationService.initialize();
} }
private RequestMatcher requestMatcher = new OrRequestMatcher( private RequestMatcher requestMatcher = new OrRequestMatcher(pathPattern("/logout/saml2/slo/{registrationId}"),
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo/{registrationId}"), pathPattern("/logout/saml2/slo"));
PathPatternRequestMatcher.withDefaults().matcher("/logout/saml2/slo"));
private final OpenSamlOperations saml = new OpenSaml4Template(); private final OpenSamlOperations saml = new OpenSaml4Template();

View File

@ -29,13 +29,13 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
public class OpenSaml4AuthenticationRequestResolverTests { public class OpenSaml4AuthenticationRequestResolverTests {
@ -92,7 +92,7 @@ public class OpenSaml4AuthenticationRequestResolverTests {
RelyingPartyRegistrationResolver relyingParties = mock(RelyingPartyRegistrationResolver.class); RelyingPartyRegistrationResolver relyingParties = mock(RelyingPartyRegistrationResolver.class);
given(relyingParties.resolve(any(), any())).willReturn(this.registration); given(relyingParties.resolve(any(), any())).willReturn(this.registration);
OpenSaml4AuthenticationRequestResolver resolver = new OpenSaml4AuthenticationRequestResolver(relyingParties); OpenSaml4AuthenticationRequestResolver resolver = new OpenSaml4AuthenticationRequestResolver(relyingParties);
resolver.setRequestMatcher(new AntPathRequestMatcher("/custom/authentication/{registrationId}")); resolver.setRequestMatcher(pathPattern("/custom/authentication/{registrationId}"));
Saml2RedirectAuthenticationRequest authnRequest = resolver Saml2RedirectAuthenticationRequest authnRequest = resolver
.resolve(givenRequest("/custom/authentication/registration-id")); .resolve(givenRequest("/custom/authentication/registration-id"));

View File

@ -29,13 +29,13 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.web.servlet.TestMockHttpServletRequests; import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
public class OpenSaml5AuthenticationRequestResolverTests { public class OpenSaml5AuthenticationRequestResolverTests {
@ -92,7 +92,7 @@ public class OpenSaml5AuthenticationRequestResolverTests {
RelyingPartyRegistrationResolver relyingParties = mock(RelyingPartyRegistrationResolver.class); RelyingPartyRegistrationResolver relyingParties = mock(RelyingPartyRegistrationResolver.class);
given(relyingParties.resolve(any(), any())).willReturn(this.registration); given(relyingParties.resolve(any(), any())).willReturn(this.registration);
OpenSaml5AuthenticationRequestResolver resolver = new OpenSaml5AuthenticationRequestResolver(relyingParties); OpenSaml5AuthenticationRequestResolver resolver = new OpenSaml5AuthenticationRequestResolver(relyingParties);
resolver.setRequestMatcher(new AntPathRequestMatcher("/custom/authentication/{registrationId}")); resolver.setRequestMatcher(pathPattern("/custom/authentication/{registrationId}"));
Saml2RedirectAuthenticationRequest authnRequest = resolver Saml2RedirectAuthenticationRequest authnRequest = resolver
.resolve(givenRequest("/custom/authentication/registration-id")); .resolve(givenRequest("/custom/authentication/registration-id"));

View File

@ -34,7 +34,6 @@ import org.springframework.security.saml2.provider.service.metadata.Saml2Metadat
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; 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.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations; import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -44,6 +43,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoInteractions;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
/** /**
* Tests for {@link Saml2MetadataFilter} * Tests for {@link Saml2MetadataFilter}
@ -129,7 +129,7 @@ public class Saml2MetadataFilterTests {
@Test @Test
public void doFilterWhenCustomRequestMatcherThenUses() throws Exception { public void doFilterWhenCustomRequestMatcherThenUses() throws Exception {
MockHttpServletRequest request = uri("/path"); MockHttpServletRequest request = uri("/path");
this.filter.setRequestMatcher(new AntPathRequestMatcher("/path")); this.filter.setRequestMatcher(pathPattern("/path"));
this.filter.doFilter(request, this.response, this.chain); this.filter.doFilter(request, this.response, this.chain);
verifyNoInteractions(this.chain); verifyNoInteractions(this.chain);
verify(this.repository).findByRegistrationId("path"); verify(this.repository).findByRegistrationId("path");
@ -159,7 +159,7 @@ public class Saml2MetadataFilterTests {
RelyingPartyRegistrationResolver resolver = new DefaultRelyingPartyRegistrationResolver( RelyingPartyRegistrationResolver resolver = new DefaultRelyingPartyRegistrationResolver(
(id) -> this.repository.findByRegistrationId("registration-id")); (id) -> this.repository.findByRegistrationId("registration-id"));
this.filter = new Saml2MetadataFilter(resolver, this.resolver); this.filter = new Saml2MetadataFilter(resolver, this.resolver);
this.filter.setRequestMatcher(new AntPathRequestMatcher("/metadata")); this.filter.setRequestMatcher(pathPattern("/metadata"));
MockHttpServletRequest request = uri("/metadata"); MockHttpServletRequest request = uri("/metadata");
this.filter.doFilter(request, this.response, new MockFilterChain()); this.filter.doFilter(request, this.response, new MockFilterChain());
verify(this.repository).findByRegistrationId("registration-id"); verify(this.repository).findByRegistrationId("registration-id");
@ -173,7 +173,7 @@ public class Saml2MetadataFilterTests {
given(this.resolver.resolve(any(RelyingPartyRegistration.class))).willReturn("metadata"); given(this.resolver.resolve(any(RelyingPartyRegistration.class))).willReturn("metadata");
this.filter = new Saml2MetadataFilter((id) -> this.repository.findByRegistrationId("registration-id"), this.filter = new Saml2MetadataFilter((id) -> this.repository.findByRegistrationId("registration-id"),
this.resolver); this.resolver);
this.filter.setRequestMatcher(new AntPathRequestMatcher("/metadata")); this.filter.setRequestMatcher(pathPattern("/metadata"));
MockHttpServletRequest request = uri("/metadata"); MockHttpServletRequest request = uri("/metadata");
this.filter.doFilter(request, this.response, new MockFilterChain()); this.filter.doFilter(request, this.response, new MockFilterChain());
verify(this.repository).findByRegistrationId("registration-id"); verify(this.repository).findByRegistrationId("registration-id");

View File

@ -43,7 +43,6 @@ import org.springframework.security.saml2.provider.service.web.Saml2Authenticati
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter; import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -54,6 +53,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoInteractions;
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
public class Saml2WebSsoAuthenticationFilterTests { public class Saml2WebSsoAuthenticationFilterTests {
@ -225,7 +225,7 @@ public class Saml2WebSsoAuthenticationFilterTests {
given(this.repository.findByRegistrationId("registration-id")).willReturn(registration); given(this.repository.findByRegistrationId("registration-id")).willReturn(registration);
given(this.authenticationManager.authenticate(authentication)).willReturn(authentication); given(this.authenticationManager.authenticate(authentication)).willReturn(authentication);
String loginProcessingUrl = "/{registrationId}/login/saml2/sso"; String loginProcessingUrl = "/{registrationId}/login/saml2/sso";
RequestMatcher matcher = new AntPathRequestMatcher(loginProcessingUrl); RequestMatcher matcher = pathPattern(loginProcessingUrl);
DefaultRelyingPartyRegistrationResolver delegate = new DefaultRelyingPartyRegistrationResolver(this.repository); DefaultRelyingPartyRegistrationResolver delegate = new DefaultRelyingPartyRegistrationResolver(this.repository);
RelyingPartyRegistrationResolver resolver = (request, id) -> { RelyingPartyRegistrationResolver resolver = (request, id) -> {
String registrationId = matcher.matcher(request).getVariables().get("registrationId"); String registrationId = matcher.matcher(request).getVariables().get("registrationId");