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

Kotlin环境Spring调用AuthenticationManager认证抛出StackOverflowError

问题根因

该问题是Kotlin语法特性与Spring Security的AOP代理逻辑冲突导致的无限递归调用:
Kotlin中类、类成员方法默认均为final修饰,不可被继承/重写。你编写的SecurityConfig配置类、重写的authenticationManagerBean()方法均未添加open修饰符解除final限制,导致Spring无法基于CGLIB生成配置类的目标类代理,只能退化为JDK动态代理生成基于接口的代理对象,最终造成AuthenticationManager实例的循环引用,调用authenticate方法时进入无限递归,触发栈溢出。
完全相同的配置在Java环境可正常运行的原因是:Java中类、成员方法默认均为非final,重写的authenticationManagerBean()方法可被CGLIB正常代理,不会出现代理对象循环嵌套的问题。

异常栈对应循环链路

从重复打印的栈帧可以明确看到死循环的调用路径:

  1. JDK动态代理生成的$Proxy99.authenticate()方法被触发
  2. 代理逻辑将调用转发给内部持有的ProviderManager.authenticate()
  3. ProviderManager内部委托的AuthenticationManager实例是WebSecurityConfigurerAdapter$AuthenticationManagerDelegator,继续调用其authenticate()方法
  4. AuthenticationManagerDelegator持有的委托对象又回到第一步的JDK动态代理实例,循环往复直到栈空间耗尽抛出StackOverflowError
修复方案

给SecurityConfig类、重写的authenticationManagerBean()方法添加open修饰符,允许CGLIB生成目标类代理即可解决问题,修正后的核心配置代码如下:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
// 类添加open修饰,解除final限制
open class SecurityConfig : WebSecurityConfigurerAdapter() {

    override fun configure(http: HttpSecurity) {
        http
            .csrf().disable()
    }

    @Bean
    // 移除不必要的可空返回值声明
    fun passwordEncoder(): BCryptPasswordEncoder = BCryptPasswordEncoder()

    @Bean
    // 重写的Bean方法添加open修饰
    override fun authenticationManagerBean(): AuthenticationManager = 
        super.authenticationManagerBean()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:57:27