Przeglądaj źródła

Integration Test for DefaultLoginPageGeneratingFilterTests

Add a minimal test to ensure that
DelegatingMissingAuthorityAccessDeniedHandler and
DefaultLoginPageGeneratingFilterTests work together properly.

Issue gh-18002
Rob Winch 1 tydzień temu
rodzic
commit
9595d37c14

+ 29 - 2
web/src/test/java/org/springframework/security/web/authentication/DefaultLoginPageGeneratingFilterTests.java

@@ -17,7 +17,9 @@
 package org.springframework.security.web.authentication;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 
 import jakarta.servlet.FilterChain;
 import jakarta.servlet.ServletException;
@@ -27,9 +29,15 @@ import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.TestAuthentication;
+import org.springframework.security.authorization.AuthorizationDeniedException;
+import org.springframework.security.authorization.FactorAuthorizationDecision;
+import org.springframework.security.authorization.RequiredFactor;
+import org.springframework.security.authorization.RequiredFactorError;
+import org.springframework.security.core.GrantedAuthorities;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.security.core.context.SecurityContextImpl;
 import org.springframework.security.web.WebAttributes;
+import org.springframework.security.web.access.DelegatingMissingAuthorityAccessDeniedHandler;
 import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.servlet.TestMockHttpServletRequests;
 
@@ -204,8 +212,9 @@ public class DefaultLoginPageGeneratingFilterTests {
 		filter.setOneTimeTokenEnabled(true);
 		filter.setOneTimeTokenGenerationUrl("/ott/authenticate");
 		MockHttpServletResponse response = new MockHttpServletResponse();
-		filter.doFilter(TestMockHttpServletRequests.get("/login?factor.type=ott&factor.reason=missing").build(),
-				response, this.chain);
+		MockHttpServletRequest loginRequest = createLoginRequestFromMissingAuthority(
+				GrantedAuthorities.FACTOR_OTT_AUTHORITY);
+		filter.doFilter(loginRequest, response, this.chain);
 		assertThat(response.getContentAsString()).contains("Request a One-Time Token");
 		assertThat(response.getContentAsString()).contains("""
 				      <form id="ott-form" class="login-form" method="post" action="/ott/authenticate">
@@ -251,6 +260,24 @@ public class DefaultLoginPageGeneratingFilterTests {
 		assertThat(response.getContentAsString()).contains("Password");
 	}
 
+	private MockHttpServletRequest createLoginRequestFromMissingAuthority(String factorAuthority)
+			throws ServletException, IOException {
+		LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint("/login");
+		List<RequiredFactorError> factorErrors = new ArrayList<>();
+		DelegatingMissingAuthorityAccessDeniedHandler.Builder handlerBldr = DelegatingMissingAuthorityAccessDeniedHandler
+			.builder();
+		handlerBldr.addEntryPointFor(entryPoint, factorAuthority);
+		RequiredFactor requiredFactor = RequiredFactor.withAuthority(factorAuthority).build();
+		RequiredFactorError factorError = RequiredFactorError.createMissing(requiredFactor);
+		factorErrors.add(factorError);
+		DelegatingMissingAuthorityAccessDeniedHandler handler = handlerBldr.build();
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		MockHttpServletResponse response = new MockHttpServletResponse();
+		FactorAuthorizationDecision decision = new FactorAuthorizationDecision(factorErrors);
+		handler.handle(request, response, new AuthorizationDeniedException("", decision));
+		return TestMockHttpServletRequests.get(response.getRedirectedUrl()).build();
+	}
+
 	@Test
 	public void generateWhenAuthenticatedThenReadOnlyUsername() throws Exception {
 		SecurityContextHolderStrategy strategy = mock(SecurityContextHolderStrategy.class);