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 org.jspecify.annotations.Nullable; | ||||
| 
 | ||||
| import org.springframework.security.config.Customizer; | ||||
| import org.springframework.security.config.annotation.web.HttpSecurityBuilder; | ||||
| 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 LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> defaultEntryPointMappings = new LinkedHashMap<>(); | ||||
| 	private DelegatingAuthenticationEntryPoint.@Nullable Builder defaultEntryPoint; | ||||
| 
 | ||||
| 	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, | ||||
| 			RequestMatcher preferredMatcher) { | ||||
| 		this.defaultEntryPointMappings.put(preferredMatcher, entryPoint); | ||||
| 		if (this.defaultEntryPoint == null) { | ||||
| 			this.defaultEntryPoint = DelegatingAuthenticationEntryPoint.builder(); | ||||
| 		} | ||||
| 		this.defaultEntryPoint.addEntryPointFor(entryPoint, preferredMatcher); | ||||
| 		return this; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -235,16 +240,10 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>> | |||
| 	} | ||||
| 
 | ||||
| 	private AuthenticationEntryPoint createDefaultEntryPoint(H http) { | ||||
| 		if (this.defaultEntryPointMappings.isEmpty()) { | ||||
| 		if (this.defaultEntryPoint == null) { | ||||
| 			return new Http403ForbiddenEntryPoint(); | ||||
| 		} | ||||
| 		if (this.defaultEntryPointMappings.size() == 1) { | ||||
| 			return this.defaultEntryPointMappings.values().iterator().next(); | ||||
| 		} | ||||
| 		DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint( | ||||
| 				this.defaultEntryPointMappings); | ||||
| 		entryPoint.setDefaultEntryPoint(this.defaultEntryPointMappings.values().iterator().next()); | ||||
| 		return entryPoint; | ||||
| 		return this.defaultEntryPoint.build(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  |  | |||
|  | @ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configurers; | |||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.LinkedHashMap; | ||||
| 
 | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
| 
 | ||||
|  | @ -103,11 +102,12 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> | |||
| 	 */ | ||||
| 	public HttpBasicConfigurer() { | ||||
| 		realmName(DEFAULT_REALM); | ||||
| 		LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>(); | ||||
| 		entryPoints.put(X_REQUESTED_WITH, new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); | ||||
| 		DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); | ||||
| 		defaultEntryPoint.setDefaultEntryPoint(this.basicAuthEntryPoint); | ||||
| 		this.authenticationEntryPoint = defaultEntryPoint; | ||||
| 		// @formatter:off | ||||
| 		this.authenticationEntryPoint = DelegatingAuthenticationEntryPoint.builder() | ||||
| 				.addEntryPointFor(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), X_REQUESTED_WITH) | ||||
| 				.defaultEntryPoint(this.basicAuthEntryPoint) | ||||
| 				.build(); | ||||
| 		// @formatter:on | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.cl | |||
| import java.lang.reflect.Field; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
|  | @ -553,13 +552,15 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> | |||
| 		RequestMatcher notXRequestedWith = new NegatedRequestMatcher( | ||||
| 				new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); | ||||
| 		RequestMatcher formLoginNotEnabled = getFormLoginNotEnabledRequestMatcher(http); | ||||
| 		LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>(); | ||||
| 		LoginUrlAuthenticationEntryPoint loginUrlEntryPoint = new LoginUrlAuthenticationEntryPoint(providerLoginPage); | ||||
| 		entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher), | ||||
| 				formLoginNotEnabled), loginUrlEntryPoint); | ||||
| 		DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); | ||||
| 		loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint()); | ||||
| 		return loginEntryPoint; | ||||
| 		RequestMatcher loginUrlMatcher = new AndRequestMatcher(notXRequestedWith, | ||||
| 				new NegatedRequestMatcher(defaultLoginPageMatcher), formLoginNotEnabled); | ||||
| 		// @formatter:off | ||||
| 		return DelegatingAuthenticationEntryPoint.builder() | ||||
| 			.addEntryPointFor(loginUrlEntryPoint, loginUrlMatcher) | ||||
| 			.defaultEntryPoint(getAuthenticationEntryPoint()) | ||||
| 			.build(); | ||||
| 		// @formatter:on | ||||
| 	} | ||||
| 
 | ||||
| 	private RequestMatcher getFormLoginNotEnabledRequestMatcher(B http) { | ||||
|  |  | |||
|  | @ -339,13 +339,15 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>> | |||
| 				new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); | ||||
| 		RequestMatcher notXRequestedWith = new NegatedRequestMatcher( | ||||
| 				new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); | ||||
| 		LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>(); | ||||
| 		LoginUrlAuthenticationEntryPoint loginUrlEntryPoint = new LoginUrlAuthenticationEntryPoint(providerLoginPage); | ||||
| 		entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)), | ||||
| 				loginUrlEntryPoint); | ||||
| 		DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); | ||||
| 		loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint()); | ||||
| 		return loginEntryPoint; | ||||
| 		RequestMatcher loginUrlMatcher = new AndRequestMatcher(notXRequestedWith, | ||||
| 				new NegatedRequestMatcher(defaultLoginPageMatcher)); | ||||
| 		// @formatter:off | ||||
| 		return DelegatingAuthenticationEntryPoint.builder() | ||||
| 				.addEntryPointFor(loginUrlEntryPoint, loginUrlMatcher) | ||||
| 				.defaultEntryPoint(getAuthenticationEntryPoint()) | ||||
| 				.build(); | ||||
| 		// @formatter:on | ||||
| 	} | ||||
| 
 | ||||
| 	private void setAuthenticationRequestRepository(B http, | ||||
|  |  | |||
|  | @ -17,13 +17,18 @@ | |||
| package org.springframework.security.web.authentication; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import jakarta.servlet.ServletException; | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import org.apache.commons.logging.Log; | ||||
| import org.apache.commons.logging.LogFactory; | ||||
| import org.jspecify.annotations.Nullable; | ||||
| 
 | ||||
| import org.springframework.beans.factory.InitializingBean; | ||||
| 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.RequestMatcher; | ||||
| import org.springframework.security.web.util.matcher.RequestMatcherEditor; | ||||
| import org.springframework.security.web.util.matcher.RequestMatcherEntry; | ||||
| import org.springframework.util.Assert; | ||||
| 
 | ||||
| /** | ||||
|  | @ -64,22 +70,63 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo | |||
| 
 | ||||
| 	private static final Log logger = LogFactory.getLog(DelegatingAuthenticationEntryPoint.class); | ||||
| 
 | ||||
| 	private final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints; | ||||
| 	private final List<RequestMatcherEntry<AuthenticationEntryPoint>> entryPoints; | ||||
| 
 | ||||
| 	@SuppressWarnings("NullAway.Init") | ||||
| 	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.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 | ||||
| 	public void commence(HttpServletRequest request, HttpServletResponse response, | ||||
| 			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)); | ||||
| 			if (requestMatcher.matches(request)) { | ||||
| 				AuthenticationEntryPoint entryPoint = this.entryPoints.get(requestMatcher); | ||||
| 				AuthenticationEntryPoint entryPoint = entry.getEntry(); | ||||
| 				logger.debug(LogMessage.format("Match found! Executing %s", entryPoint)); | ||||
| 				entryPoint.commence(request, response, authException); | ||||
| 				return; | ||||
|  | @ -92,7 +139,10 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo | |||
| 
 | ||||
| 	/** | ||||
| 	 * EntryPoint which is used when no RequestMatcher returned true | ||||
| 	 * @deprecated Use | ||||
| 	 * {@link #DelegatingAuthenticationEntryPoint(AuthenticationEntryPoint, List)} | ||||
| 	 */ | ||||
| 	@Deprecated(forRemoval = true) | ||||
| 	public void setDefaultEntryPoint(AuthenticationEntryPoint defaultEntryPoint) { | ||||
| 		this.defaultEntryPoint = defaultEntryPoint; | ||||
| 	} | ||||
|  | @ -103,4 +153,76 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo | |||
| 		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; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
| 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.security.web.AuthenticationEntryPoint; | ||||
| 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.Mockito.mock; | ||||
| import static org.mockito.Mockito.never; | ||||
|  | @ -52,8 +56,6 @@ public class DelegatingAuthenticationEntryPointTests { | |||
| 	public void before() { | ||||
| 		this.defaultEntryPoint = mock(AuthenticationEntryPoint.class); | ||||
| 		this.entryPoints = new LinkedHashMap<>(); | ||||
| 		this.daep = new DelegatingAuthenticationEntryPoint(this.entryPoints); | ||||
| 		this.daep.setDefaultEntryPoint(this.defaultEntryPoint); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
|  | @ -62,6 +64,8 @@ public class DelegatingAuthenticationEntryPointTests { | |||
| 		RequestMatcher firstRM = mock(RequestMatcher.class); | ||||
| 		given(firstRM.matches(this.request)).willReturn(false); | ||||
| 		this.entryPoints.put(firstRM, firstAEP); | ||||
| 		this.daep = new DelegatingAuthenticationEntryPoint(this.entryPoints); | ||||
| 		this.daep.setDefaultEntryPoint(this.defaultEntryPoint); | ||||
| 		this.daep.commence(this.request, null, null); | ||||
| 		verify(this.defaultEntryPoint).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); | ||||
| 		this.entryPoints.put(firstRM, firstAEP); | ||||
| 		this.entryPoints.put(secondRM, secondAEP); | ||||
| 		this.daep = new DelegatingAuthenticationEntryPoint(this.entryPoints); | ||||
| 		this.daep.setDefaultEntryPoint(this.defaultEntryPoint); | ||||
| 		this.daep.commence(this.request, null, null); | ||||
| 		verify(firstAEP).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); | ||||
| 		this.entryPoints.put(firstRM, firstAEP); | ||||
| 		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); | ||||
| 		verify(secondAEP).commence(this.request, null, null); | ||||
| 		verify(firstAEP, never()).commence(this.request, null, null); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue