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

Spring Boot Security POST请求/login报StackOverflowError排查

根因定位

java.lang.StackOverflowError 由AuthenticationManager循环委托引用导致,两个authenticate方法形成无出口的递归调用链:

  • 自定义CustomAuthenticationFilter持有的AuthenticationManager实例,与WebSecurityConfigurerAdapter内部生成的委托类AuthenticationManagerDelegator形成自引用
  • 调用链路:Filter触发AuthenticationManagerDelegator.authenticate() → 委托给ProviderManager处理 → ProviderManager未找到可处理认证的Provider时,调用持有的父级AuthenticationManager → 父级实例就是最初的AuthenticationManagerDelegator → 回到链路起点无限循环,直到栈内存耗尽。
高频触发场景
  • 重写WebSecurityConfig的authenticationManagerBean()方法时,未调用super.authenticationManagerBean(),手动构建ProviderManager返回时错误绑定了委托对象
  • 给自定义认证Filter设置AuthenticationManager时,未引用容器中暴露的单例Bean,而是重复从HttpSecurity上下文中获取未初始化完成的Manager实例,形成自引用
  • 未向AuthenticationManager注册可处理用户名密码认证的DaoAuthenticationProvider,导致ProviderManager直接走父级Manager兜底逻辑,刚好命中循环引用
修复步骤

按以下顺序检查配置,逐点修正:

  1. 修正AuthenticationManager Bean的暴露逻辑
    不要手动new ProviderManager实例,直接调用父类方法生成标准Bean:
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        // 禁止自定义构建逻辑,直接返回父类生成的实例
        return super.authenticationManagerBean();
    }
    
  2. 修正自定义Filter的Manager注入逻辑
    给CustomAuthenticationFilter设置AuthenticationManager时,直接引用上一步暴露的容器级Bean,不要从HttpSecurity共享对象中重复获取:
    @Bean
    public CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
        CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
        // 直接引用容器中注册的AuthenticationManager单例
        filter.setAuthenticationManager(authenticationManagerBean());
        // 自定义登录路径
        filter.setFilterProcessesUrl("/login");
        return filter;
    }
    
  3. 补全认证提供者配置
    注册DaoAuthenticationProvider,绑定你实现的UserDetailsService和PasswordEncoder,避免ProviderManager走父级兜底逻辑:
    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(yourUserDetailsService);
        provider.setPasswordEncoder(yourPasswordEncoder);
        return provider;
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 注册自定义认证提供者,不要留空配置
        auth.authenticationProvider(daoAuthenticationProvider());
    }
    
  4. 修正过滤链注册逻辑
    将自定义认证Filter添加到过滤链的正确位置,替换默认的UsernamePasswordAuthenticationFilter,避免重复注册:
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/login", "/refresh").permitAll()
                .anyRequest().authenticated()
                .and()
                // 将自定义Filter加入过滤链
                .addFilter(customAuthenticationFilter());
    }
    
验证方式

配置修改完成后重启服务,在ProviderManager.authenticate方法入口打调试断点,首次进入时检查当前实例的parent字段值,如果不是WebSecurityConfigurerAdapter$AuthenticationManagerDelegator类型,说明循环引用已经解除,发送POST登录请求即可正常进入认证逻辑,不会再触发栈溢出。

内容的提问来源于stack exchange,提问作者Abhinav Saxena

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 21:03:40