|
@@ -28,6 +28,7 @@ import org.springframework.context.ApplicationContext;
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
import org.springframework.security.authentication.AuthenticationProvider;
|
|
import org.springframework.security.authentication.AuthenticationProvider;
|
|
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;
|
|
@@ -56,7 +57,6 @@ import org.springframework.security.web.authentication.DelegatingAuthenticationE
|
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
|
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
|
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
|
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
|
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
|
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
|
|
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
|
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
|
import org.springframework.security.web.util.matcher.ParameterRequestMatcher;
|
|
import org.springframework.security.web.util.matcher.ParameterRequestMatcher;
|
|
@@ -127,15 +127,11 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
|
|
|
|
private String[] authenticationRequestParams = { "registrationId={registrationId}" };
|
|
private String[] authenticationRequestParams = { "registrationId={registrationId}" };
|
|
|
|
|
|
- private RequestMatcher authenticationRequestMatcher = RequestMatchers.anyOf(
|
|
|
|
- new AntPathRequestMatcher(Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI),
|
|
|
|
- new AntPathQueryRequestMatcher(this.authenticationRequestUri, this.authenticationRequestParams));
|
|
|
|
|
|
+ private RequestMatcher authenticationRequestMatcher;
|
|
|
|
|
|
private Saml2AuthenticationRequestResolver authenticationRequestResolver;
|
|
private Saml2AuthenticationRequestResolver authenticationRequestResolver;
|
|
|
|
|
|
- private RequestMatcher loginProcessingUrl = RequestMatchers.anyOf(
|
|
|
|
- new AntPathRequestMatcher(Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI),
|
|
|
|
- new AntPathRequestMatcher("/login/saml2/sso"));
|
|
|
|
|
|
+ private RequestMatcher loginProcessingUrl;
|
|
|
|
|
|
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
|
|
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
|
|
|
|
|
|
@@ -238,8 +234,8 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
this.authenticationRequestUri = parts[0];
|
|
this.authenticationRequestUri = parts[0];
|
|
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 AntPathQueryRequestMatcher(this.authenticationRequestUri,
|
|
|
|
- this.authenticationRequestParams);
|
|
|
|
|
|
+ this.authenticationRequestMatcher = new PathQueryRequestMatcher(
|
|
|
|
+ RequestMatcherFactory.matcher(this.authenticationRequestUri), this.authenticationRequestParams);
|
|
return this;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -256,13 +252,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 = new AntPathRequestMatcher(loginProcessingUrl);
|
|
|
|
|
|
+ this.loginProcessingUrl = RequestMatcherFactory.matcher(loginProcessingUrl);
|
|
return this;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
|
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
|
- return new AntPathRequestMatcher(loginProcessingUrl);
|
|
|
|
|
|
+ return RequestMatcherFactory.matcher(loginProcessingUrl);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -284,7 +280,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
relyingPartyRegistrationRepository(http);
|
|
relyingPartyRegistrationRepository(http);
|
|
this.saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter(getAuthenticationConverter(http));
|
|
this.saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter(getAuthenticationConverter(http));
|
|
this.saml2WebSsoAuthenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
|
this.saml2WebSsoAuthenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
|
- this.saml2WebSsoAuthenticationFilter.setRequiresAuthenticationRequestMatcher(this.loginProcessingUrl);
|
|
|
|
|
|
+ this.saml2WebSsoAuthenticationFilter.setRequiresAuthenticationRequestMatcher(getLoginProcessingEndpoint());
|
|
setAuthenticationRequestRepository(http, this.saml2WebSsoAuthenticationFilter);
|
|
setAuthenticationRequestRepository(http, this.saml2WebSsoAuthenticationFilter);
|
|
setAuthenticationFilter(this.saml2WebSsoAuthenticationFilter);
|
|
setAuthenticationFilter(this.saml2WebSsoAuthenticationFilter);
|
|
if (StringUtils.hasText(this.loginPage)) {
|
|
if (StringUtils.hasText(this.loginPage)) {
|
|
@@ -340,8 +336,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 = new AntPathRequestMatcher(this.getLoginPage());
|
|
|
|
- RequestMatcher faviconMatcher = new AntPathRequestMatcher("/favicon.ico");
|
|
|
|
|
|
+ RequestMatcher loginPageMatcher = RequestMatcherFactory.matcher(this.getLoginPage());
|
|
|
|
+ RequestMatcher faviconMatcher = RequestMatcherFactory.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);
|
|
@@ -376,17 +372,38 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
if (USE_OPENSAML_5) {
|
|
if (USE_OPENSAML_5) {
|
|
OpenSaml5AuthenticationRequestResolver openSamlAuthenticationRequestResolver = new OpenSaml5AuthenticationRequestResolver(
|
|
OpenSaml5AuthenticationRequestResolver openSamlAuthenticationRequestResolver = new OpenSaml5AuthenticationRequestResolver(
|
|
relyingPartyRegistrationRepository(http));
|
|
relyingPartyRegistrationRepository(http));
|
|
- openSamlAuthenticationRequestResolver.setRequestMatcher(this.authenticationRequestMatcher);
|
|
|
|
|
|
+ openSamlAuthenticationRequestResolver.setRequestMatcher(getAuthenticationRequestMatcher());
|
|
return openSamlAuthenticationRequestResolver;
|
|
return openSamlAuthenticationRequestResolver;
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
OpenSaml4AuthenticationRequestResolver openSamlAuthenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(
|
|
OpenSaml4AuthenticationRequestResolver openSamlAuthenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(
|
|
relyingPartyRegistrationRepository(http));
|
|
relyingPartyRegistrationRepository(http));
|
|
- openSamlAuthenticationRequestResolver.setRequestMatcher(this.authenticationRequestMatcher);
|
|
|
|
|
|
+ openSamlAuthenticationRequestResolver.setRequestMatcher(getAuthenticationRequestMatcher());
|
|
return openSamlAuthenticationRequestResolver;
|
|
return openSamlAuthenticationRequestResolver;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private RequestMatcher getAuthenticationRequestMatcher() {
|
|
|
|
+ if (this.authenticationRequestMatcher == null) {
|
|
|
|
+ this.authenticationRequestMatcher = RequestMatchers.anyOf(
|
|
|
|
+ RequestMatcherFactory
|
|
|
|
+ .matcher(Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI),
|
|
|
|
+ new PathQueryRequestMatcher(RequestMatcherFactory.matcher(this.authenticationRequestUri),
|
|
|
|
+ this.authenticationRequestParams));
|
|
|
|
+ }
|
|
|
|
+ return this.authenticationRequestMatcher;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private RequestMatcher getLoginProcessingEndpoint() {
|
|
|
|
+ if (this.loginProcessingUrl == null) {
|
|
|
|
+ this.loginProcessingUrl = RequestMatchers.anyOf(
|
|
|
|
+ RequestMatcherFactory.matcher(Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI),
|
|
|
|
+ RequestMatcherFactory.matcher("/login/saml2/sso"));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return this.loginProcessingUrl;
|
|
|
|
+ }
|
|
|
|
+
|
|
private AuthenticationConverter getAuthenticationConverter(B http) {
|
|
private AuthenticationConverter getAuthenticationConverter(B http) {
|
|
if (this.authenticationConverter != null) {
|
|
if (this.authenticationConverter != null) {
|
|
return this.authenticationConverter;
|
|
return this.authenticationConverter;
|
|
@@ -407,7 +424,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
OpenSaml5AuthenticationTokenConverter converter = new OpenSaml5AuthenticationTokenConverter(
|
|
OpenSaml5AuthenticationTokenConverter converter = new OpenSaml5AuthenticationTokenConverter(
|
|
this.relyingPartyRegistrationRepository);
|
|
this.relyingPartyRegistrationRepository);
|
|
converter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http));
|
|
converter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http));
|
|
- converter.setRequestMatcher(this.loginProcessingUrl);
|
|
|
|
|
|
+ converter.setRequestMatcher(getLoginProcessingEndpoint());
|
|
return converter;
|
|
return converter;
|
|
}
|
|
}
|
|
authenticationConverterBean = getBeanOrNull(http, OpenSaml4AuthenticationTokenConverter.class);
|
|
authenticationConverterBean = getBeanOrNull(http, OpenSaml4AuthenticationTokenConverter.class);
|
|
@@ -417,7 +434,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
OpenSaml4AuthenticationTokenConverter converter = new OpenSaml4AuthenticationTokenConverter(
|
|
OpenSaml4AuthenticationTokenConverter converter = new OpenSaml4AuthenticationTokenConverter(
|
|
this.relyingPartyRegistrationRepository);
|
|
this.relyingPartyRegistrationRepository);
|
|
converter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http));
|
|
converter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http));
|
|
- converter.setRequestMatcher(this.loginProcessingUrl);
|
|
|
|
|
|
+ converter.setRequestMatcher(getLoginProcessingEndpoint());
|
|
return converter;
|
|
return converter;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -441,7 +458,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
if (csrf == null) {
|
|
if (csrf == null) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- csrf.ignoringRequestMatchers(this.loginProcessingUrl);
|
|
|
|
|
|
+ csrf.ignoringRequestMatchers(getLoginProcessingEndpoint());
|
|
}
|
|
}
|
|
|
|
|
|
private void initDefaultLoginFilter(B http) {
|
|
private void initDefaultLoginFilter(B http) {
|
|
@@ -509,13 +526,13 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- static class AntPathQueryRequestMatcher implements RequestMatcher {
|
|
|
|
|
|
+ static class PathQueryRequestMatcher implements RequestMatcher {
|
|
|
|
|
|
private final RequestMatcher matcher;
|
|
private final RequestMatcher matcher;
|
|
|
|
|
|
- AntPathQueryRequestMatcher(String path, String... params) {
|
|
|
|
|
|
+ PathQueryRequestMatcher(RequestMatcher pathMatcher, String... params) {
|
|
List<RequestMatcher> matchers = new ArrayList<>();
|
|
List<RequestMatcher> matchers = new ArrayList<>();
|
|
- matchers.add(new AntPathRequestMatcher(path));
|
|
|
|
|
|
+ matchers.add(pathMatcher);
|
|
for (String param : params) {
|
|
for (String param : params) {
|
|
String[] parts = param.split("=");
|
|
String[] parts = param.split("=");
|
|
if (parts.length == 1) {
|
|
if (parts.length == 1) {
|