You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7升级至3.0.1后Logout功能失效的问题排查求助

Spring Boot 2.7升级至3.0.1后Logout功能失效的问题排查求助

各位大佬好,我最近把Spring Boot项目从2.7版本升级到了3.0.1,按照官方指引调整了WebSecurity配置(替换WebSecurityConfigurerAdapter为SecurityFilterChain Bean),项目能正常启动也能成功登录,但Logout功能完全失效了,想请大家帮忙看看哪里出问题了。

旧版本(2.7)的WebSecurity配置

@Configuration
@EnableWebSecurity(debug = false)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // 开启OAuth2登录,所有请求需认证
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .oauth2Login()
                .and()
            // 配置Logout:使用OIDC登出处理器,登出时销毁Session
            .logout()
                .logoutSuccessHandler(oidcLogoutSuccessHandler())
                .invalidateHttpSession(true)
                .and()
            // 添加安全Header
            .headers()
                .addHeaderWriter(new StaticHeadersWriter("Referrer-Policy", "same-origin"))
                .addHeaderWriter(new StaticHeadersWriter("Strict-Transport-Security", "max-age=31536000; includeSubDomains"))
                .and()
            // 配置CSRF:使用Cookie存储CSRF Token
            .csrf()
                .csrfTokenRepository(getCookieCsrfTokenRepository());
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        // 忽略Swagger、健康检查接口的安全校验
        return web -> web.ignoring().antMatchers("/**/health", "/swagger-ui/**", "/v3/**");
    }

    private CookieCsrfTokenRepository getCookieCsrfTokenRepository() {
        CookieCsrfTokenRepository cookieCsrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
        cookieCsrfTokenRepository.setCookiePath("/");
        return cookieCsrfTokenRepository;
    }

    private OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() {
        OidcClientInitiatedLogoutSuccessHandler successHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
        successHandler.setPostLogoutRedirectUri("{baseUrl}" + RouteConstants.IDP_LOGIN);
        return successHandler;
    }
}

升级后(3.0.1)的WebSecurity配置

@Configuration
@EnableWebSecurity(debug = false)
public class WebSecurityConfig {

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 开启OAuth2登录,所有请求需认证
            .authorizeHttpRequests()
                .anyRequest().authenticated()
                .and()
            .oauth2Login()
                .and()
            // 配置Logout:使用OIDC登出处理器,登出时销毁Session
            .logout()
                .logoutSuccessHandler(oidcLogoutSuccessHandler())
                .invalidateHttpSession(true)
                .and()
            // 添加安全Header
            .headers()
                .addHeaderWriter(new StaticHeadersWriter("Referrer-Policy", "same-origin"))
                .addHeaderWriter(new StaticHeadersWriter("Strict-Transport-Security", "max-age=31536000; includeSubDomains"))
                .and()
            // 配置CSRF:使用Cookie存储CSRF Token
            .csrf()
                .csrfTokenRepository(getCookieCsrfTokenRepository());
        return http.build();
    }

    // webSecurityCustomizer方法和其他工具方法和旧版本完全一致
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return web -> web.ignoring().antMatchers("/**/health", "/swagger-ui/**", "/v3/**");
    }

    private CookieCsrfTokenRepository getCookieCsrfTokenRepository() {
        CookieCsrfTokenRepository cookieCsrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
        cookieCsrfTokenRepository.setCookiePath("/");
        return cookieCsrfTokenRepository;
    }

    private OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() {
        OidcClientInitiatedLogoutSuccessHandler successHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
        successHandler.setPostLogoutRedirectUri("{baseUrl}" + RouteConstants.IDP_LOGIN);
        return successHandler;
    }
}

另外,为了让/**路径匹配正常工作,我添加了这个配置:

spring.mvc.pathmatch.matching-strategy=ant-path-matcher

问题现象

  1. 登录后,请求http://localhost/api/v1/authentication/idp_login的响应Cookie里没有XSRF-TOKEN,但升级前是有的;
  2. 发起Logout请求(POST /logout)时,直接返回403 Forbidden,日志里显示CSRF Token无效:
org.springframework.security.web.FilterChainProxy - Securing POST /logout
2023-01-21 TRACE org.springframework.security.web.FilterChainProxy - Invoking DisableEncodeUrlFilter (1/15)
2023-01-21 TRACE org.springframework.security.web.FilterChainProxy - Invoking WebAsyncManagerIntegrationFilter (2/15)
2023-01-21 TRACE org.springframework.security.web.FilterChainProxy - Invoking SecurityContextHolderFilter (3/15)
2023-01-21 TRACE org.springframework.security.web.FilterChainProxy - Invoking HeaderWriterFilter (4/15)
2023-01-21 TRACE org.springframework.security.web.FilterChainProxy - Invoking CsrfFilter (5/15)
2023-01-21 DEBUG org.springframework.security.web.csrf.CsrfFilter - Invalid CSRF token found for http://localhost/api/v1/authentication/logout
2023-01-21 DEBUG org.springframework.security.web.access.AccessDeniedHandlerImpl - Responding with 403 status code
...(后续日志省略)

想请教各位,除了已经做的改动,还需要调整什么才能让Logout功能恢复正常?

备注:内容来源于stack exchange,提问作者Suzan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 14:37:41