diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index a13b9975a0..df8344f10a 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -36,6 +36,7 @@ import org.springframework.security.web.server.authentication.RedirectServerAuth import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler; import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler; +import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; import org.springframework.security.web.server.authentication.logout.LogoutWebFilter; import org.springframework.security.web.server.authentication.logout.SecurityContextServerLogoutHandler; import org.springframework.security.web.server.authentication.logout.ServerLogoutHandler; @@ -503,11 +504,20 @@ public class ServerHttpSecurity { private ServerAuthenticationFailureHandler serverAuthenticationFailureHandler; + private ServerAuthenticationSuccessHandler serverAuthenticationSuccessHandler = new RedirectServerAuthenticationSuccessHandler("/"); + public FormLoginBuilder authenticationManager(ReactiveAuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; return this; } + public FormLoginBuilder serverAuthenticationSuccessHandler( + ServerAuthenticationSuccessHandler serverAuthenticationSuccessHandler) { + Assert.notNull(serverAuthenticationSuccessHandler, "serverAuthenticationSuccessHandler cannot be null"); + this.serverAuthenticationSuccessHandler = serverAuthenticationSuccessHandler; + return this; + } + public FormLoginBuilder loginPage(String loginPage) { this.serverAuthenticationEntryPoint = new RedirectServerAuthenticationEntryPoint(loginPage); this.requiresAuthenticationMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, loginPage); @@ -557,7 +567,7 @@ public class ServerHttpSecurity { authenticationFilter.setRequiresAuthenticationMatcher(this.requiresAuthenticationMatcher); authenticationFilter.setServerAuthenticationFailureHandler(this.serverAuthenticationFailureHandler); authenticationFilter.setAuthenticationConverter(new ServerFormLoginAuthenticationConverter()); - authenticationFilter.setServerAuthenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/")); + authenticationFilter.setServerAuthenticationSuccessHandler(this.serverAuthenticationSuccessHandler); authenticationFilter.setServerSecurityContextRepository(this.serverSecurityContextRepository); http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.FORM_LOGIN); } diff --git a/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java b/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java index 2c7f76b8a8..06b4a00c81 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java @@ -29,8 +29,10 @@ import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.htmlunit.server.WebTestClientHtmlUnitDriverBuilder; import org.springframework.security.test.web.reactive.server.WebTestClientBuilder; +import org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapperTests; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.WebFilterChainProxy; +import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; import org.springframework.stereotype.Controller; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.bind.annotation.GetMapping; @@ -119,6 +121,36 @@ public class FormLoginTests { homePage.assertAt(); } + @Test + public void authenticationSuccess() { + SecurityWebFilterChain securityWebFilter = this.http + .authorizeExchange() + .anyExchange().authenticated() + .and() + .formLogin() + .serverAuthenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/custom")) + .and() + .build(); + + WebTestClient webTestClient = WebTestClientBuilder + .bindToWebFilters(securityWebFilter) + .build(); + + WebDriver driver = WebTestClientHtmlUnitDriverBuilder + .webTestClientSetup(webTestClient) + .build(); + + DefaultLoginPage loginPage = HomePage.to(driver, DefaultLoginPage.class) + .assertAt(); + + HomePage homePage = loginPage.loginForm() + .username("user") + .password("password") + .submit(HomePage.class); + + assertThat(driver.getCurrentUrl()).endsWith("/custom"); + } + public static class CustomLoginPage { private WebDriver driver;