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

Spring Security Kotlin中Repository类字段注入失败问题排查

问题根源

你在SecurityConfig里犯了一个关键错误:虽然通过构造函数注入了Spring容器管理的AuthenticationSuccessHandler实例,但在配置OAuth2登录的successHandler时,你手动新建了一个未被Spring管理的AuthenticationSuccessHandler()对象。这个手动创建的对象不在Spring的容器生命周期里,Spring不会为它注入userRepository,所以调用时就会触发lateinit未初始化的异常。

另外,你的AuthenticationSuccessHandler使用@Autowired标注lateinit属性的方式虽然可行,但Kotlin里更推荐用构造函数注入,能从根源避免这类未初始化问题。

修复步骤

1. 修正SecurityConfig的配置

把successHandler(AuthenticationSuccessHandler())改成直接使用构造函数注入的实例:

@EnableWebSecurity
@Configuration
class SecurityConfig(private val authenticationSuccessHandler: AuthenticationSuccessHandler) {
    @Throws(Exception::class)
    @Bean
    fun override(http: HttpSecurity): SecurityFilterChain {
        return http
                .csrf { csrf -> csrf.disable() }
                .authorizeRequests { auth ->
                    auth.antMatchers("/api/brackets").authenticated()
                    auth.antMatchers("/**").permitAll()
                }
                .oauth2Login()
                .successHandler(authenticationSuccessHandler) // 这里用注入的实例,不要新建
                .and()
                .build()
    }
}

2. 优化AuthenticationSuccessHandler的注入方式(可选但推荐)

把@Autowired的lateinit属性改成构造函数注入,这样Spring会在创建实例时直接注入userRepository,彻底避免未初始化问题:

@Component
class AuthenticationSuccessHandler(
    private val userRepository: UserRepository // 构造函数注入
) : SavedRequestAwareAuthenticationSuccessHandler() {

    private val redirectStrategy: RedirectStrategy = DefaultRedirectStrategy()
    private val logger: Logger = LoggerFactory.getLogger(javaClass)
    
    @Throws(ServletException::class, IOException::class)
    override fun onAuthenticationSuccess(request: HttpServletRequest, response: HttpServletResponse, authentication: Authentication) {
        val requestCache: RequestCache = HttpSessionRequestCache()
        val savedRequest: SavedRequest? = requestCache.getRequest(request, response) // 处理可能的null返回
        val userDetails: DefaultOidcUser = authentication.principal as DefaultOidcUser
        logger.info(userDetails.idToken.tokenValue)
        userRepository.save(User(userDetails.name, userDetails.email, AuthService.GOOGLE))
        redirectStrategy.sendRedirect(request, response, "/api/testAuth")
    }
}

注意:原代码里requestCache.getRequest(request, response)可能返回null,所以变量类型要改成SavedRequest?,避免空指针异常。

补充说明
  • Spring只会对自己容器管理的Bean进行依赖注入,手动new出来的对象不属于容器,所以不会自动注入依赖。
  • Kotlin的构造函数注入是更安全的方式,能在编译期就检查依赖是否存在,而lateinit属性是运行期检查,容易出现未初始化的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 11:05:22