mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-10-23 10:48:51 +00:00
DelegatingAuthenticationEntryPoint uses RequestMatcherEntry
Closes gh-17915
This commit is contained in:
parent
c905ac359d
commit
9a3ae4b867
@ -18,6 +18,8 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
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.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
@ -71,7 +73,7 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
private AccessDeniedHandler accessDeniedHandler;
|
private AccessDeniedHandler accessDeniedHandler;
|
||||||
|
|
||||||
private LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> defaultEntryPointMappings = new LinkedHashMap<>();
|
private DelegatingAuthenticationEntryPoint.@Nullable Builder defaultEntryPoint;
|
||||||
|
|
||||||
private LinkedHashMap<RequestMatcher, AccessDeniedHandler> defaultDeniedHandlerMappings = new LinkedHashMap<>();
|
private LinkedHashMap<RequestMatcher, AccessDeniedHandler> defaultDeniedHandlerMappings = new LinkedHashMap<>();
|
||||||
|
|
||||||
@ -161,7 +163,10 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*/
|
*/
|
||||||
public ExceptionHandlingConfigurer<H> defaultAuthenticationEntryPointFor(AuthenticationEntryPoint entryPoint,
|
public ExceptionHandlingConfigurer<H> defaultAuthenticationEntryPointFor(AuthenticationEntryPoint entryPoint,
|
||||||
RequestMatcher preferredMatcher) {
|
RequestMatcher preferredMatcher) {
|
||||||
this.defaultEntryPointMappings.put(preferredMatcher, entryPoint);
|
if (this.defaultEntryPoint == null) {
|
||||||
|
this.defaultEntryPoint = DelegatingAuthenticationEntryPoint.builder();
|
||||||
|
}
|
||||||
|
this.defaultEntryPoint.addEntryPointFor(entryPoint, preferredMatcher);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,16 +240,10 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private AuthenticationEntryPoint createDefaultEntryPoint(H http) {
|
private AuthenticationEntryPoint createDefaultEntryPoint(H http) {
|
||||||
if (this.defaultEntryPointMappings.isEmpty()) {
|
if (this.defaultEntryPoint == null) {
|
||||||
return new Http403ForbiddenEntryPoint();
|
return new Http403ForbiddenEntryPoint();
|
||||||
}
|
}
|
||||||
if (this.defaultEntryPointMappings.size() == 1) {
|
return this.defaultEntryPoint.build();
|
||||||
return this.defaultEntryPointMappings.values().iterator().next();
|
|
||||||
}
|
|
||||||
DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(
|
|
||||||
this.defaultEntryPointMappings);
|
|
||||||
entryPoint.setDefaultEntryPoint(this.defaultEntryPointMappings.values().iterator().next());
|
|
||||||
return entryPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@ -103,11 +102,12 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>>
|
|||||||
*/
|
*/
|
||||||
public HttpBasicConfigurer() {
|
public HttpBasicConfigurer() {
|
||||||
realmName(DEFAULT_REALM);
|
realmName(DEFAULT_REALM);
|
||||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
|
// @formatter:off
|
||||||
entryPoints.put(X_REQUESTED_WITH, new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
this.authenticationEntryPoint = DelegatingAuthenticationEntryPoint.builder()
|
||||||
DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
|
.addEntryPointFor(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), X_REQUESTED_WITH)
|
||||||
defaultEntryPoint.setDefaultEntryPoint(this.basicAuthEntryPoint);
|
.defaultEntryPoint(this.basicAuthEntryPoint)
|
||||||
this.authenticationEntryPoint = defaultEntryPoint;
|
.build();
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,7 +19,6 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.cl
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
@ -553,13 +552,15 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
||||||
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
||||||
RequestMatcher formLoginNotEnabled = getFormLoginNotEnabledRequestMatcher(http);
|
RequestMatcher formLoginNotEnabled = getFormLoginNotEnabledRequestMatcher(http);
|
||||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
|
|
||||||
LoginUrlAuthenticationEntryPoint loginUrlEntryPoint = new LoginUrlAuthenticationEntryPoint(providerLoginPage);
|
LoginUrlAuthenticationEntryPoint loginUrlEntryPoint = new LoginUrlAuthenticationEntryPoint(providerLoginPage);
|
||||||
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher),
|
RequestMatcher loginUrlMatcher = new AndRequestMatcher(notXRequestedWith,
|
||||||
formLoginNotEnabled), loginUrlEntryPoint);
|
new NegatedRequestMatcher(defaultLoginPageMatcher), formLoginNotEnabled);
|
||||||
DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
|
// @formatter:off
|
||||||
loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());
|
return DelegatingAuthenticationEntryPoint.builder()
|
||||||
return loginEntryPoint;
|
.addEntryPointFor(loginUrlEntryPoint, loginUrlMatcher)
|
||||||
|
.defaultEntryPoint(getAuthenticationEntryPoint())
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestMatcher getFormLoginNotEnabledRequestMatcher(B http) {
|
private RequestMatcher getFormLoginNotEnabledRequestMatcher(B http) {
|
||||||
|
@ -339,13 +339,15 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||||||
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
|
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
|
||||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
|
||||||
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
|
||||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
|
|
||||||
LoginUrlAuthenticationEntryPoint loginUrlEntryPoint = new LoginUrlAuthenticationEntryPoint(providerLoginPage);
|
LoginUrlAuthenticationEntryPoint loginUrlEntryPoint = new LoginUrlAuthenticationEntryPoint(providerLoginPage);
|
||||||
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
|
RequestMatcher loginUrlMatcher = new AndRequestMatcher(notXRequestedWith,
|
||||||
loginUrlEntryPoint);
|
new NegatedRequestMatcher(defaultLoginPageMatcher));
|
||||||
DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
|
// @formatter:off
|
||||||
loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());
|
return DelegatingAuthenticationEntryPoint.builder()
|
||||||
return loginEntryPoint;
|
.addEntryPointFor(loginUrlEntryPoint, loginUrlMatcher)
|
||||||
|
.defaultEntryPoint(getAuthenticationEntryPoint())
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAuthenticationRequestRepository(B http,
|
private void setAuthenticationRequestRepository(B http,
|
||||||
|
@ -17,13 +17,18 @@
|
|||||||
package org.springframework.security.web.authentication;
|
package org.springframework.security.web.authentication;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
@ -32,6 +37,7 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
|||||||
import org.springframework.security.web.util.matcher.ELRequestMatcher;
|
import org.springframework.security.web.util.matcher.ELRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcherEditor;
|
import org.springframework.security.web.util.matcher.RequestMatcherEditor;
|
||||||
|
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,22 +70,63 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo
|
|||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(DelegatingAuthenticationEntryPoint.class);
|
private static final Log logger = LogFactory.getLog(DelegatingAuthenticationEntryPoint.class);
|
||||||
|
|
||||||
private final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints;
|
private final List<RequestMatcherEntry<AuthenticationEntryPoint>> entryPoints;
|
||||||
|
|
||||||
@SuppressWarnings("NullAway.Init")
|
@SuppressWarnings("NullAway.Init")
|
||||||
private AuthenticationEntryPoint defaultEntryPoint;
|
private AuthenticationEntryPoint defaultEntryPoint;
|
||||||
|
|
||||||
public DelegatingAuthenticationEntryPoint(LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) {
|
/**
|
||||||
|
* Creates a new instance with the provided mappings.
|
||||||
|
* @param entryPoints the mapping of {@link RequestMatcher} to
|
||||||
|
* {@link AuthenticationEntryPoint}. Cannot be null or empty.
|
||||||
|
* @param defaultEntryPoint the default {@link AuthenticationEntryPoint}. Cannot be
|
||||||
|
* null.
|
||||||
|
*/
|
||||||
|
public DelegatingAuthenticationEntryPoint(AuthenticationEntryPoint defaultEntryPoint,
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint>... entryPoints) {
|
||||||
|
Assert.notEmpty(entryPoints, "entryPoints cannot be empty");
|
||||||
|
Assert.notNull(defaultEntryPoint, "defaultEntryPoint cannot be null");
|
||||||
|
this.entryPoints = Arrays.asList(entryPoints);
|
||||||
|
this.defaultEntryPoint = defaultEntryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance with the provided mappings.
|
||||||
|
* @param defaultEntryPoint the default {@link AuthenticationEntryPoint}. Cannot be
|
||||||
|
* null.
|
||||||
|
* @param entryPoints the mapping of {@link RequestMatcher} to
|
||||||
|
* {@link AuthenticationEntryPoint}. Cannot be null or empty.
|
||||||
|
*/
|
||||||
|
public DelegatingAuthenticationEntryPoint(AuthenticationEntryPoint defaultEntryPoint,
|
||||||
|
List<RequestMatcherEntry<AuthenticationEntryPoint>> entryPoints) {
|
||||||
|
Assert.notEmpty(entryPoints, "entryPoints cannot be empty");
|
||||||
|
Assert.notNull(defaultEntryPoint, "defaultEntryPoint cannot be null");
|
||||||
this.entryPoints = entryPoints;
|
this.entryPoints = entryPoints;
|
||||||
|
this.defaultEntryPoint = defaultEntryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance.
|
||||||
|
* @param entryPoints
|
||||||
|
* @deprecated Use
|
||||||
|
* {@link #DelegatingAuthenticationEntryPoint(AuthenticationEntryPoint, List)}
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
|
public DelegatingAuthenticationEntryPoint(LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) {
|
||||||
|
this.entryPoints = entryPoints.entrySet()
|
||||||
|
.stream()
|
||||||
|
.map((e) -> new RequestMatcherEntry<>(e.getKey(), e.getValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||||
AuthenticationException authException) throws IOException, ServletException {
|
AuthenticationException authException) throws IOException, ServletException {
|
||||||
for (RequestMatcher requestMatcher : this.entryPoints.keySet()) {
|
for (RequestMatcherEntry<AuthenticationEntryPoint> entry : this.entryPoints) {
|
||||||
|
RequestMatcher requestMatcher = entry.getRequestMatcher();
|
||||||
logger.debug(LogMessage.format("Trying to match using %s", requestMatcher));
|
logger.debug(LogMessage.format("Trying to match using %s", requestMatcher));
|
||||||
if (requestMatcher.matches(request)) {
|
if (requestMatcher.matches(request)) {
|
||||||
AuthenticationEntryPoint entryPoint = this.entryPoints.get(requestMatcher);
|
AuthenticationEntryPoint entryPoint = entry.getEntry();
|
||||||
logger.debug(LogMessage.format("Match found! Executing %s", entryPoint));
|
logger.debug(LogMessage.format("Match found! Executing %s", entryPoint));
|
||||||
entryPoint.commence(request, response, authException);
|
entryPoint.commence(request, response, authException);
|
||||||
return;
|
return;
|
||||||
@ -92,7 +139,10 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* EntryPoint which is used when no RequestMatcher returned true
|
* EntryPoint which is used when no RequestMatcher returned true
|
||||||
|
* @deprecated Use
|
||||||
|
* {@link #DelegatingAuthenticationEntryPoint(AuthenticationEntryPoint, List)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
public void setDefaultEntryPoint(AuthenticationEntryPoint defaultEntryPoint) {
|
public void setDefaultEntryPoint(AuthenticationEntryPoint defaultEntryPoint) {
|
||||||
this.defaultEntryPoint = defaultEntryPoint;
|
this.defaultEntryPoint = defaultEntryPoint;
|
||||||
}
|
}
|
||||||
@ -103,4 +153,76 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo
|
|||||||
Assert.notNull(this.defaultEntryPoint, "defaultEntryPoint must be specified");
|
Assert.notNull(this.defaultEntryPoint, "defaultEntryPoint must be specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Builder}
|
||||||
|
* @return the new {@link Builder}
|
||||||
|
*/
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to build a new instance of {@link DelegatingAuthenticationEntryPoint}.
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private @Nullable AuthenticationEntryPoint defaultEntryPoint;
|
||||||
|
|
||||||
|
private List<RequestMatcherEntry<AuthenticationEntryPoint>> entryPoints = new ArrayList<RequestMatcherEntry<AuthenticationEntryPoint>>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default {@link AuthenticationEntryPoint} if none match. The default is
|
||||||
|
* to use the first {@link AuthenticationEntryPoint} added in
|
||||||
|
* {@link #addEntryPointFor(AuthenticationEntryPoint, RequestMatcher)}.
|
||||||
|
* @param defaultEntryPoint the default {@link AuthenticationEntryPoint} to use.
|
||||||
|
* @return the {@link Builder} for further customization.
|
||||||
|
*/
|
||||||
|
public Builder defaultEntryPoint(@Nullable AuthenticationEntryPoint defaultEntryPoint) {
|
||||||
|
this.defaultEntryPoint = defaultEntryPoint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an {@link AuthenticationEntryPoint} for the provided
|
||||||
|
* {@link RequestMatcher}.
|
||||||
|
* @param entryPoint the {@link AuthenticationEntryPoint} to use. Cannot be null.
|
||||||
|
* @param requestMatcher the {@link RequestMatcher} to use. Cannot be null.
|
||||||
|
* @return the {@link Builder} for further customization.
|
||||||
|
*/
|
||||||
|
public Builder addEntryPointFor(AuthenticationEntryPoint entryPoint, RequestMatcher requestMatcher) {
|
||||||
|
Assert.notNull(entryPoint, "entryPoint cannot be null");
|
||||||
|
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
|
||||||
|
this.entryPoints.add(new RequestMatcherEntry<>(requestMatcher, entryPoint));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the {@link AuthenticationEntryPoint}. If the
|
||||||
|
* {@link #defaultEntryPoint(AuthenticationEntryPoint)} is not set, then the first
|
||||||
|
* {@link #addEntryPointFor(AuthenticationEntryPoint, RequestMatcher)} is used as
|
||||||
|
* the default. If the {@link #defaultEntryPoint(AuthenticationEntryPoint)} is not
|
||||||
|
* set and there is only a single
|
||||||
|
* {@link #addEntryPointFor(AuthenticationEntryPoint, RequestMatcher)}, then the
|
||||||
|
* {@link AuthenticationEntryPoint} is returned rather than wrapping it in
|
||||||
|
* {@link DelegatingAuthenticationEntryPoint}.
|
||||||
|
* @return the {@link AuthenticationEntryPoint} to use.
|
||||||
|
*/
|
||||||
|
public AuthenticationEntryPoint build() {
|
||||||
|
Assert.notEmpty(this.entryPoints, "entryPoints cannot be empty");
|
||||||
|
AuthenticationEntryPoint defaultEntryPoint = this.defaultEntryPoint;
|
||||||
|
if (defaultEntryPoint == null) {
|
||||||
|
AuthenticationEntryPoint firstAuthenticationEntryPoint = this.entryPoints.get(0).getEntry();
|
||||||
|
if (this.entryPoints.size() == 1) {
|
||||||
|
return firstAuthenticationEntryPoint;
|
||||||
|
}
|
||||||
|
defaultEntryPoint = firstAuthenticationEntryPoint;
|
||||||
|
}
|
||||||
|
return new DelegatingAuthenticationEntryPoint(defaultEntryPoint, this.entryPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.springframework.security.web.authentication;
|
package org.springframework.security.web.authentication;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@ -25,7 +27,9 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
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.never;
|
import static org.mockito.Mockito.never;
|
||||||
@ -52,8 +56,6 @@ public class DelegatingAuthenticationEntryPointTests {
|
|||||||
public void before() {
|
public void before() {
|
||||||
this.defaultEntryPoint = mock(AuthenticationEntryPoint.class);
|
this.defaultEntryPoint = mock(AuthenticationEntryPoint.class);
|
||||||
this.entryPoints = new LinkedHashMap<>();
|
this.entryPoints = new LinkedHashMap<>();
|
||||||
this.daep = new DelegatingAuthenticationEntryPoint(this.entryPoints);
|
|
||||||
this.daep.setDefaultEntryPoint(this.defaultEntryPoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -62,6 +64,8 @@ public class DelegatingAuthenticationEntryPointTests {
|
|||||||
RequestMatcher firstRM = mock(RequestMatcher.class);
|
RequestMatcher firstRM = mock(RequestMatcher.class);
|
||||||
given(firstRM.matches(this.request)).willReturn(false);
|
given(firstRM.matches(this.request)).willReturn(false);
|
||||||
this.entryPoints.put(firstRM, firstAEP);
|
this.entryPoints.put(firstRM, firstAEP);
|
||||||
|
this.daep = new DelegatingAuthenticationEntryPoint(this.entryPoints);
|
||||||
|
this.daep.setDefaultEntryPoint(this.defaultEntryPoint);
|
||||||
this.daep.commence(this.request, null, null);
|
this.daep.commence(this.request, null, null);
|
||||||
verify(this.defaultEntryPoint).commence(this.request, null, null);
|
verify(this.defaultEntryPoint).commence(this.request, null, null);
|
||||||
verify(firstAEP, never()).commence(this.request, null, null);
|
verify(firstAEP, never()).commence(this.request, null, null);
|
||||||
@ -76,6 +80,8 @@ public class DelegatingAuthenticationEntryPointTests {
|
|||||||
given(firstRM.matches(this.request)).willReturn(true);
|
given(firstRM.matches(this.request)).willReturn(true);
|
||||||
this.entryPoints.put(firstRM, firstAEP);
|
this.entryPoints.put(firstRM, firstAEP);
|
||||||
this.entryPoints.put(secondRM, secondAEP);
|
this.entryPoints.put(secondRM, secondAEP);
|
||||||
|
this.daep = new DelegatingAuthenticationEntryPoint(this.entryPoints);
|
||||||
|
this.daep.setDefaultEntryPoint(this.defaultEntryPoint);
|
||||||
this.daep.commence(this.request, null, null);
|
this.daep.commence(this.request, null, null);
|
||||||
verify(firstAEP).commence(this.request, null, null);
|
verify(firstAEP).commence(this.request, null, null);
|
||||||
verify(secondAEP, never()).commence(this.request, null, null);
|
verify(secondAEP, never()).commence(this.request, null, null);
|
||||||
@ -93,6 +99,103 @@ public class DelegatingAuthenticationEntryPointTests {
|
|||||||
given(secondRM.matches(this.request)).willReturn(true);
|
given(secondRM.matches(this.request)).willReturn(true);
|
||||||
this.entryPoints.put(firstRM, firstAEP);
|
this.entryPoints.put(firstRM, firstAEP);
|
||||||
this.entryPoints.put(secondRM, secondAEP);
|
this.entryPoints.put(secondRM, secondAEP);
|
||||||
|
this.daep = new DelegatingAuthenticationEntryPoint(this.entryPoints);
|
||||||
|
this.daep.setDefaultEntryPoint(this.defaultEntryPoint);
|
||||||
|
this.daep.commence(this.request, null, null);
|
||||||
|
verify(secondAEP).commence(this.request, null, null);
|
||||||
|
verify(firstAEP, never()).commence(this.request, null, null);
|
||||||
|
verify(this.defaultEntryPoint, never()).commence(this.request, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorAepListWhenNullEntryPoints() {
|
||||||
|
List<RequestMatcherEntry<AuthenticationEntryPoint>> entryPoints = null;
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(
|
||||||
|
() -> new DelegatingAuthenticationEntryPoint(mock(AuthenticationEntryPoint.class), entryPoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorAepListWhenEmptyEntryPoints() {
|
||||||
|
assertThatIllegalArgumentException()
|
||||||
|
.isThrownBy(() -> new DelegatingAuthenticationEntryPoint(mock(AuthenticationEntryPoint.class),
|
||||||
|
Collections.emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorAepListWhenNullDefaultEntryPoint() {
|
||||||
|
AuthenticationEntryPoint entryPoint = mock(AuthenticationEntryPoint.class);
|
||||||
|
RequestMatcher matcher = mock(RequestMatcher.class);
|
||||||
|
List<RequestMatcherEntry<AuthenticationEntryPoint>> entryPoints = List
|
||||||
|
.of(new RequestMatcherEntry<>(matcher, entryPoint));
|
||||||
|
assertThatIllegalArgumentException()
|
||||||
|
.isThrownBy(() -> new DelegatingAuthenticationEntryPoint(null, entryPoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorAepVargsWhenNullEntryPoints() {
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint>[] entryPoints = null;
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(
|
||||||
|
() -> new DelegatingAuthenticationEntryPoint(mock(AuthenticationEntryPoint.class), entryPoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorAepVargsWhenEmptyEntryPoints() {
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint>[] entryPoints = new RequestMatcherEntry[0];
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(
|
||||||
|
() -> new DelegatingAuthenticationEntryPoint(mock(AuthenticationEntryPoint.class), entryPoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorAepVargsWhenNullDefaultEntryPoint() {
|
||||||
|
AuthenticationEntryPoint entryPoint = mock(AuthenticationEntryPoint.class);
|
||||||
|
RequestMatcher matcher = mock(RequestMatcher.class);
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint>[] entryPoints = new RequestMatcherEntry[] {
|
||||||
|
new RequestMatcherEntry<>(matcher, entryPoint) };
|
||||||
|
assertThatIllegalArgumentException()
|
||||||
|
.isThrownBy(() -> new DelegatingAuthenticationEntryPoint(null, entryPoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void commenceWhenNoMatchThenDefaultEntryPoint() throws Exception {
|
||||||
|
AuthenticationEntryPoint firstAEP = mock(AuthenticationEntryPoint.class);
|
||||||
|
RequestMatcher firstRM = mock(RequestMatcher.class);
|
||||||
|
given(firstRM.matches(this.request)).willReturn(false);
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint> entry = new RequestMatcherEntry<>(firstRM, firstAEP);
|
||||||
|
this.daep = new DelegatingAuthenticationEntryPoint(this.defaultEntryPoint, entry);
|
||||||
|
this.daep.commence(this.request, null, null);
|
||||||
|
verify(this.defaultEntryPoint).commence(this.request, null, null);
|
||||||
|
verify(firstAEP, never()).commence(this.request, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void commenceWhenMatchFirstEntryPointThenOthersNotInvoked() throws Exception {
|
||||||
|
AuthenticationEntryPoint firstAEP = mock(AuthenticationEntryPoint.class);
|
||||||
|
RequestMatcher firstRM = mock(RequestMatcher.class);
|
||||||
|
given(firstRM.matches(this.request)).willReturn(true);
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint> firstEntry = new RequestMatcherEntry<>(firstRM, firstAEP);
|
||||||
|
AuthenticationEntryPoint secondAEP = mock(AuthenticationEntryPoint.class);
|
||||||
|
RequestMatcher secondRM = mock(RequestMatcher.class);
|
||||||
|
given(secondRM.matches(this.request)).willReturn(false);
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint> secondEntry = new RequestMatcherEntry<>(firstRM, firstAEP);
|
||||||
|
this.daep = new DelegatingAuthenticationEntryPoint(this.defaultEntryPoint, firstEntry, secondEntry);
|
||||||
|
this.daep.commence(this.request, null, null);
|
||||||
|
verify(firstAEP).commence(this.request, null, null);
|
||||||
|
verify(secondAEP, never()).commence(this.request, null, null);
|
||||||
|
verify(this.defaultEntryPoint, never()).commence(this.request, null, null);
|
||||||
|
verify(secondRM, never()).matches(this.request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void commenceWhenSecondMatchesThenDefaultNotInvoked() throws Exception {
|
||||||
|
AuthenticationEntryPoint firstAEP = mock(AuthenticationEntryPoint.class);
|
||||||
|
RequestMatcher firstRM = mock(RequestMatcher.class);
|
||||||
|
given(firstRM.matches(this.request)).willReturn(false);
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint> firstEntry = new RequestMatcherEntry<>(firstRM, firstAEP);
|
||||||
|
AuthenticationEntryPoint secondAEP = mock(AuthenticationEntryPoint.class);
|
||||||
|
RequestMatcher secondRM = mock(RequestMatcher.class);
|
||||||
|
given(secondRM.matches(this.request)).willReturn(true);
|
||||||
|
RequestMatcherEntry<AuthenticationEntryPoint> secondEntry = new RequestMatcherEntry<>(secondRM, secondAEP);
|
||||||
|
this.daep = new DelegatingAuthenticationEntryPoint(this.defaultEntryPoint, firstEntry, secondEntry);
|
||||||
this.daep.commence(this.request, null, null);
|
this.daep.commence(this.request, null, null);
|
||||||
verify(secondAEP).commence(this.request, null, null);
|
verify(secondAEP).commence(this.request, null, null);
|
||||||
verify(firstAEP, never()).commence(this.request, null, null);
|
verify(firstAEP, never()).commence(this.request, null, null);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user