From ccdb97743b0ef41bc33cd78e6d55f6f51b94ad1f Mon Sep 17 00:00:00 2001 From: John Niang Date: Mon, 26 May 2025 11:44:14 +0800 Subject: [PATCH] Refactor logout handler (#7470) #### What type of PR is this? /kind cleanup /area core /milestone 2.21.x #### What this PR does / why we need it: This PR corrects location of LogoutHandler instead of in LogoutSuccessHandler. LogoutHanadler should be invoked before LogoutSuccessHandler. #### Does this PR introduce a user-facing change? ```release-note None ``` --- .../security/LogoutSecurityConfigurer.java | 46 ++++++++++--------- .../TokenBasedRememberMeServices.java | 2 +- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/application/src/main/java/run/halo/app/security/LogoutSecurityConfigurer.java b/application/src/main/java/run/halo/app/security/LogoutSecurityConfigurer.java index 13bf8c168..be677740c 100644 --- a/application/src/main/java/run/halo/app/security/LogoutSecurityConfigurer.java +++ b/application/src/main/java/run/halo/app/security/LogoutSecurityConfigurer.java @@ -3,6 +3,7 @@ package run.halo.app.security; import static run.halo.app.security.authentication.WebExchangeMatchers.ignoringMediaTypeAll; import java.net.URI; +import java.util.ArrayList; import java.util.Map; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationContext; @@ -19,8 +20,10 @@ import org.springframework.security.web.server.DefaultServerRedirectStrategy; import org.springframework.security.web.server.ServerRedirectStrategy; import org.springframework.security.web.server.WebFilterExchange; import org.springframework.security.web.server.authentication.logout.DelegatingServerLogoutHandler; +import org.springframework.security.web.server.authentication.logout.SecurityContextServerLogoutHandler; import org.springframework.security.web.server.authentication.logout.ServerLogoutHandler; import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; +import org.springframework.security.web.server.context.ServerSecurityContextRepository; import org.springframework.security.web.server.savedrequest.ServerRequestCache; import org.springframework.security.web.server.savedrequest.WebSessionServerRequestCache; import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; @@ -34,15 +37,12 @@ import run.halo.app.core.user.service.UserLoginOrLogoutProcessing; import run.halo.app.core.user.service.UserService; import run.halo.app.infra.actuator.GlobalInfoService; import run.halo.app.security.authentication.SecurityConfigurer; -import run.halo.app.security.authentication.rememberme.RememberMeServices; import run.halo.app.theme.router.ModelConst; @Component @RequiredArgsConstructor @Order(0) -public class LogoutSecurityConfigurer implements SecurityConfigurer { - - private final RememberMeServices rememberMeServices; +class LogoutSecurityConfigurer implements SecurityConfigurer { private final ApplicationContext applicationContext; @@ -50,14 +50,29 @@ public class LogoutSecurityConfigurer implements SecurityConfigurer { private final ServerRequestCache serverRequestCache = new HaloServerRequestCache(); + private final ServerSecurityContextRepository securityContextRepository; + @Override public void configure(ServerHttpSecurity http) { - var serverLogoutHandlers = getLogoutHandlers(); - http.logout( - logout -> logout.logoutSuccessHandler(new LogoutSuccessHandler(serverLogoutHandlers)) + http.logout(logout -> logout + .logoutHandler(getLogoutHandler()) + .logoutSuccessHandler(new LogoutSuccessHandler()) ); } + private ServerLogoutHandler getLogoutHandler() { + var defaultLogoutHandler = new SecurityContextServerLogoutHandler(); + defaultLogoutHandler.setSecurityContextRepository(securityContextRepository); + var logoutHandlers = new ArrayList(); + logoutHandlers.add(defaultLogoutHandler); + applicationContext.getBeanProvider(ServerLogoutHandler.class) + .forEach(logoutHandlers::add); + if (logoutHandlers.size() == 1) { + return logoutHandlers.getFirst(); + } + return new DelegatingServerLogoutHandler(logoutHandlers); + } + @Bean RouterFunction logoutPage( UserService userService, @@ -93,25 +108,17 @@ public class LogoutSecurityConfigurer implements SecurityConfigurer { private class LogoutSuccessHandler implements ServerLogoutSuccessHandler { private final ServerLogoutSuccessHandler defaultHandler; - private final ServerLogoutHandler logoutHandler; - public LogoutSuccessHandler(ServerLogoutHandler... logoutHandlers) { + public LogoutSuccessHandler() { var redirectHandler = new RequestCacheRedirectLogoutSuccessHandler(); redirectHandler.setRequestCache(serverRequestCache); this.defaultHandler = redirectHandler; - if (logoutHandlers.length == 1) { - this.logoutHandler = logoutHandlers[0]; - } else { - this.logoutHandler = new DelegatingServerLogoutHandler(logoutHandlers); - } } @Override public Mono onLogoutSuccess(WebFilterExchange exchange, Authentication authentication) { - return logoutHandler.logout(exchange, authentication) - .then(rememberMeServices.loginFail(exchange.getExchange())) - .then(userLoginOrLogoutProcessing.logoutProcessing(authentication.getName())) + return userLoginOrLogoutProcessing.logoutProcessing(authentication.getName()) .then(ignoringMediaTypeAll(MediaType.APPLICATION_JSON) .matches(exchange.getExchange()) .filter(ServerWebExchangeMatcher.MatchResult::isMatch) @@ -127,11 +134,6 @@ public class LogoutSecurityConfigurer implements SecurityConfigurer { } } - private ServerLogoutHandler[] getLogoutHandlers() { - return applicationContext.getBeansOfType(ServerLogoutHandler.class).values() - .toArray(new ServerLogoutHandler[0]); - } - private static class RequestCacheRedirectLogoutSuccessHandler implements ServerLogoutSuccessHandler { diff --git a/application/src/main/java/run/halo/app/security/authentication/rememberme/TokenBasedRememberMeServices.java b/application/src/main/java/run/halo/app/security/authentication/rememberme/TokenBasedRememberMeServices.java index 6de95ecf4..6ecdf5bfa 100644 --- a/application/src/main/java/run/halo/app/security/authentication/rememberme/TokenBasedRememberMeServices.java +++ b/application/src/main/java/run/halo/app/security/authentication/rememberme/TokenBasedRememberMeServices.java @@ -367,7 +367,7 @@ public class TokenBasedRememberMeServices implements ServerLogoutHandler, Rememb log.debug("Logout of user {}", (authentication != null) ? authentication.getName() : "Unknown"); } - return onLogout(exchange, authentication); + return loginFail(exchange.getExchange()).then(onLogout(exchange, authentication)); } protected Mono onLogout(WebFilterExchange exchange, Authentication authentication) {