Spring Boot 2.7.8升级后Logout Handler阻塞,无法跳转至logoutSuccessUrl
Spring Boot 2.7.8(Spring Security 5.7.6)登出后无法重定向到指定地址
问题背景
将应用从Spring Boot 2.6.5升级至2.7.8(对应Spring Security 5.7.6),为后续升级到3.0版本做准备。升级前登出功能正常,但升级后登出流程完成后,始终无法重定向到logoutSuccessUrl()配置的地址。
过滤器链配置代码
http .authorizeHttpRequests((authz) -> authz .antMatchers("/webjars/**","/login/**","/mobile-manifest.json","/service-worker.js","/cache.manifest","/favicon.ico","/async/**","/api/**").permitAll() .anyRequest().authenticated() ) .httpBasic(withDefaults()) .formLogin(formLogin -> formLogin .loginPage("/login") .permitAll() .loginProcessingUrl("/login") .successHandler(savedRequestAwareAuthenticationSuccessHandler()) .failureUrl("/login?loginFailed=true")) .logout( logout -> logout .logoutUrl("/logout") .logoutSuccessUrl("/login?logoutSuccess=true") .invalidateHttpSession(true) .deleteCookies(COOKIE_STRING)) .rememberMe( rememberMe -> rememberMe .key(TOKEN_KEY) .rememberMeParameter(REMEMBER_ME_KEY) .tokenRepository(persistentTokenRepository()) .userDetailsService(userSvc) .tokenValiditySeconds(validitySeconds));
调试日志
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.security.web.FilterChainProxy] - Securing POST /logout [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] - Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=UserProfile [ blah blah, eventRoles=null, lastLoginDisplay=today, directoryUrl=null, groups=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=740230E1C02B57BEF504C23570FFA9EC], Granted Authorities=[]]] [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.SecurityContextPersistenceFilter] - Set SecurityContextHolder to SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=UserProfile [blah blah eventRoles=null, lastLoginDisplay=today, directoryUrl=null, groups=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=740230E1C02B57BEF504C23570FFA9EC], Granted Authorities=[]]] [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.logout.LogoutFilter] - Logging out [UsernamePasswordAuthenticationToken [Principal=UserProfile [blah blah, eventRoles=null, lastLoginDisplay=today, directoryUrl=null, groups=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=740230E1C02B57BEF504C23570FFA9EC], Granted Authorities=[]]] [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.r.PersistentTokenBasedRememberMeServices] - Logout of user username [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.r.PersistentTokenBasedRememberMeServices] - Cancelling cookie [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.jdbc.core.JdbcTemplate] - Executing prepared SQL update [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.jdbc.core.JdbcTemplate] - Executing prepared SQL statement [delete from persistent_logins where username = ?] [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.l.SecurityContextLogoutHandler] - Invalidated session F3BC69312EC05C175A0FCEC298B49D06 [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] - Did not store empty SecurityContext [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] - Did not store empty SecurityContext [https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.SecurityContextPersistenceFilter] - Cleared SecurityContextHolder to complete request
补充信息
- 浏览器始终未跳转到
/login?logoutSuccess=true,调试日志在上述最后一行终止 - CSRF已启用,登出请求通过POST方式提交
- 曾在logout配置中添加
.permitAll(),无明显效果
解决方案尝试
1. 显式指定LogoutSuccessHandler
替代logoutSuccessUrl,直接自定义重定向逻辑,避免默认处理器的潜在问题:
.logout(logout -> logout .logoutUrl("/logout") .logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.sendRedirect("/login?logoutSuccess=true"); } }) .invalidateHttpSession(true) .deleteCookies(COOKIE_STRING) )
2. 确保登出地址被允许访问
在authorizeHttpRequests中显式添加/logout到允许列表:
.authorizeHttpRequests((authz) -> authz .antMatchers("/webjars/**","/login/**","/logout","/mobile-manifest.json","/service-worker.js","/cache.manifest","/favicon.ico","/async/**","/api/**").permitAll() .anyRequest().authenticated() )
3. 排查自定义过滤器拦截
检查应用中是否存在自定义Filter或拦截器,在LogoutFilter之后执行并修改了响应。可暂时禁用自定义过滤器,测试登出重定向是否恢复正常。
4. 临时禁用Remember-Me配置
日志显示remember-me服务在处理登出,可能其清理逻辑影响了响应流程。暂时注释remember-me配置,测试登出功能是否正常,再逐步排查。
5. 检查前端请求类型
如果登出请求是通过AJAX发起的,浏览器不会自动处理重定向响应。需要在前端代码中监听响应,手动执行页面跳转。
内容的提问来源于stack exchange,提问作者jn4
相关产品推荐
相关产品推荐

