Spring Boot 安全配置中出现不满足的依赖/循环引用错误

问题描述 投票:0回答:1

我正在使用 Spring Security 开发 Spring Boot 应用程序,并且在 AppConfig.java 文件中遇到了依赖项注入问题。除非我在构造函数中使用 @Lazy 注释,否则应用程序将不会启动。我宁愿避免使用 @Lazy,但在尝试配置没有它的安全性时,我遇到了循环引用错误。

这是我当前的 AppConfig.java:

@Configuration
@EnableWebSecurity
public class AppConfig extends WebSecurityConfigurerAdapter {

    private final CurrentUserService currentUserService;
    private final SessionFilter sessionFilter;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    @Lazy
    public AppConfig(CurrentUserService currentUserService, SessionFilter sessionFilter, PasswordEncoder passwordEncoder) {
        this.currentUserService = currentUserService;
        this.sessionFilter = sessionFilter;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http = http.cors().and().csrf().disable();

        http = http.exceptionHandling().authenticationEntryPoint(
                (request, response, authException) -> {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
                }
        ).and();

        http.authorizeRequests().antMatchers("/api/login").permitAll().anyRequest().authenticated();

        http.addFilterBefore(sessionFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

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

问题:

如果我删除@Lazy,应用程序将无法启动并抛出以下错误:

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appConfig' defined in file [C:\path\to\AppConfig.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'appConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?

我尝试切换到字段注入以避免构造函数注入,如下所示:

@Autowired
private CurrentUserService currentUserService;
@Autowired
private SessionFilter sessionFilter;
@Autowired
private PasswordEncoder passwordEncoder;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
}

但是我遇到了类似的错误:

Error creating bean with name 'appConfig': Unsatisfied dependency expressed through field 'passwordEncoder'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'appConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?

我的问题:

How can I resolve this circular dependency without relying on @Lazy?
Is there a better approach for injecting these dependencies in a Spring Security configuration?
Are there specific patterns or workarounds for avoiding circular references in Spring Boot security setups?

任何建议或见解将不胜感激!

java spring spring-boot spring-security endpoint
1个回答
0
投票

发生此错误是因为您在注入它的同一类中创建

PasswordEncoder

最好的解决方案是根本不自动连接

PasswordEncoder
(或
CurrentUserService
)。

看来这些实例仅在

configure(AuthenticationManagerBuilder auth)
方法中使用,这是多余的。

PasswordEncoder
UserDetailsService
注册为 bean 就足以让 Spring Security 检测到它们并在您的配置中使用它们。

换句话说,您应该删除以下代码:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
}

应用程序仍将以完全相同的方式运行。

© www.soinside.com 2019 - 2024. All rights reserved.