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

Spring Boot应用启动失败:AuthenticationManager Bean循环依赖求助

Spring Boot电商后台安全配置循环依赖问题解决

错误日志

2022-12-31T00:48:58.789+05:30 ERROR 10168 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :


应用启动失败


描述:

应用上下文(application context)中部分Bean的依赖形成循环:

┌──->──┐
| authenticationManager 定义在类路径资源 [com/ecommerce/admin/config/AdminConfiguration.class]
└──<-──┘

处理建议:

尽管允许循环引用,但无法打破Bean之间的依赖循环。请更新应用以移除该依赖循环。

进程已结束,退出代码 0

问题代码(AdminConfiguration)

package com.ecommerce.admin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@EnableWebSecurity
@Configuration
public class AdminConfiguration {

    @Bean
    public UserDetailsService userDetailsService() {
      return new AdminServiceConfig();
    }
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
    }
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationManager authenticationManager) throws Exception {
      return authenticationManager;
    }
    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
      DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
      provider.setUserDetailsService(userDetailsService());
      provider.setPasswordEncoder(passwordEncoder());
      return provider;
    }
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
           http
               .csrf().disable()
               .authorizeHttpRequests()
                   .and()
               .formLogin()
                   .loginPage("/login")
                   .loginProcessingUrl("/do-login")
                   .defaultSuccessUrl("/admin/index")
                   .permitAll()
                   .and()
               .logout()
                   .invalidateHttpSession(true)
                   .clearAuthentication(true)
                   .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                   .logoutSuccessUrl("/login/logout")
                   .permitAll();
           DefaultSecurityFilterChain build = http.build();
           return build;
    }
}

问题原因

循环依赖直接源于错误的authenticationManager Bean定义:该方法将AuthenticationManager作为入参,同时返回该实例,相当于Bean创建时需要先拿到自身实例,形成自循环依赖。

解决方案

方案1:正确构建AuthenticationManager(推荐,适配Spring Security 5.7+)

修改authenticationManager的Bean定义,通过AuthenticationManagerBuilder结合已定义的DaoAuthenticationProvider构建实例,同时补充资源授权规则:

package com.ecommerce.admin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@EnableWebSecurity
@Configuration
public class AdminConfiguration {

    @Bean
    public UserDetailsService userDetailsService() {
        return new AdminServiceConfig();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 正确构建AuthenticationManager,避免循环依赖
    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        authBuilder.authenticationProvider(daoAuthenticationProvider());
        return authBuilder.build();
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService());
        provider.setPasswordEncoder(passwordEncoder());
        return provider;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeHttpRequests(auth -> auth
                        // 放行登录相关路径,其余路径需认证
                        .requestMatchers("/login", "/login/logout").permitAll()
                        .anyRequest().authenticated()
                )
                .formLogin(form -> form
                        .loginPage("/login")
                        .loginProcessingUrl("/do-login")
                        .defaultSuccessUrl("/admin/index")
                        .permitAll()
                )
                .logout(logout -> logout
                        .invalidateHttpSession(true)
                        .clearAuthentication(true)
                        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                        .logoutSuccessUrl("/login/logout")
                        .permitAll()
                );
        return http.build();
    }
}

方案2:移除多余的AuthenticationManager Bean

如果业务代码中没有手动注入AuthenticationManager的需求,可直接删除错误的authenticationManager方法,Spring Security会自动构建并使用合适的实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 05:10:20