创建名为'springSecurityConfig'的bean时出错:所请求的bean目前正在创建中:是否存在无法解决的循环引用?

7 浏览
0 Comments

创建名为'springSecurityConfig'的bean时出错:所请求的bean目前正在创建中:是否存在无法解决的循环引用?

我在使用BCryptPasswordEncoder对内存中的用户密码进行编码时遇到了错误。以下是我的SpringSecurityConfig文件:\n

SpringSecurityConfig类

\n

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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
    }
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password(passwordEncoder().encode("password"))
                .roles("USER");
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

\n我该如何正确编码密码,以避免出现bean创建错误?

0
0 Comments

错误的原因是由于循环依赖导致的,解决方法是创建一个单独的配置类并将PasswordEncoder方法移动到该类中。示例代码如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class PasswordEncoderConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

然后将SpringSecurityConfig类修改如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password(passwordEncoder.encode("password"))
            .roles("USER");
    }
}

通过将PasswordEncoder方法移动到单独的配置类中,避免了循环依赖的问题,并将该配置类通过@Autowired注入到SpringSecurityConfig中使用。这样就解决了循环依赖导致的问题。

0
0 Comments

问题出现的原因是由于bean之间存在循环依赖关系,导致创建bean时发生错误。具体来说,SpringSecurityConfig类中的UserDetailsService bean依赖于PasswordEncoder bean,而PasswordEncoder bean又依赖于SpringSecurityConfig类。

解决这个问题的方法是通过将UserDetailsService bean的依赖关系移动到SpringSecurityConfig类的构造函数中。这样一来,SpringSecurityConfig类的创建不再依赖于PasswordEncoder bean,从而解决了循环依赖的问题。

修改后的代码如下所示:

public class SpringSecurityConfig {
    private final PasswordEncoder encoder;
    public SpringSecurityConfig(PasswordEncoder encoder) {
        this.encoder = encoder;
    }
    public SecurityFilterChain appSecurity(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
        return http.build();
    }
    public UserDetailsService userDetailsService() {
        User admin = User.withUsername("admin")
                .password(encoder.encode("password"))
                .roles("USER").build();
        return new InMemoryUserDetailsManager(admin);
    }
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

通过将PasswordEncoder作为构造函数的参数传入SpringSecurityConfig类中,解决了循环依赖问题。

更多详情可以参考Spring Security的官方文档:https://docs.spring.io/spring-security/reference/5.7.0-M3/servlet/authentication/passwords/in-memory.html

0