spring-security 声明AuthenticationManager Bean时引发异常“无法将DaoAuthenticationConfigurer应用于已构建的对象”

xoefb8l8  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(473)

我的UserServiceImpl类扩展了UserDetailsService接口,并且我已经覆盖了loadUserByUsername()方法,我声明了一个AuthenticationManager bean,并使用构建器,将我的userDetailsService实现和首选密码编码器传递给它。
下面是我的安全配置类:

@Configuration
@EnableWebSecurity
public class UserManagmentConfig {

@Autowired
private UserDetailsService userDetailsService;

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

@Bean
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder builder) throws Exception {
    return builder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()).and().build();
}
}

以及我的WebAuthorization配置:

public class WebAuthorizationConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.formLogin();
        http.authorizeRequests().anyRequest().authenticated();
        return http.build();
    }
}

这是我在启动应用程序时遇到的异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationManager' defined in class path resource [app/ticketme/securityconfig/UserManagmentConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Factory method 'authenticationManager' threw exception; nested exception is java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer@14d513ca to already built object
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.21.jar:5.3.21]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.1.jar:2.7.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.1.jar:2.7.1]
    at app.ticketme.Main.main(Main.java:10) ~[classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Factory method 'authenticationManager' threw exception; nested exception is java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer@14d513ca to already built object
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.21.jar:5.3.21]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.21.jar:5.3.21]
    ... 19 common frames omitted
Caused by: java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer@14d513ca to already built object
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.add(AbstractConfiguredSecurityBuilder.java:182) ~[spring-security-config-5.7.2.jar:5.7.2]
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.apply(AbstractConfiguredSecurityBuilder.java:125) ~[spring-security-config-5.7.2.jar:5.7.2]
    at org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.apply(AuthenticationManagerBuilder.java:280) ~[spring-security-config-5.7.2.jar:5.7.2]
    at org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.userDetailsService(AuthenticationManagerBuilder.java:182) ~[spring-security-config-5.7.2.jar:5.7.2]
    at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$DefaultPasswordEncoderAuthenticationManagerBuilder.userDetailsService(AuthenticationConfiguration.java:291) ~[spring-security-config-5.7.2.jar:5.7.2]
    at app.ticketme.securityconfig.UserManagmentConfig.authenticationManager(UserManagmentConfig.java:31) ~[classes/:na]
    at app.ticketme.securityconfig.UserManagmentConfig$$EnhancerBySpringCGLIB$$a7378581.CGLIB$authenticationManager$1(<generated>) ~[classes/:na]
    at app.ticketme.securityconfig.UserManagmentConfig$$EnhancerBySpringCGLIB$$a7378581$$FastClassBySpringCGLIB$$2537ee3.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.21.jar:5.3.21]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.21.jar:5.3.21]
    at app.ticketme.securityconfig.UserManagmentConfig$$EnhancerBySpringCGLIB$$a7378581.authenticationManager(<generated>) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.21.jar:5.3.21]
    ... 20 common frames omitted

可悲的是,大多数YouTube教程都使用了过时的WebSecurityConfigurerAdapter,我在这里做错了什么?任何帮助都表示感谢。

dy2hfwbg

dy2hfwbg1#

当您启用formLogin时,框架将使用您示例化的提供的bean为您构建一个身份验证管理器。
我不知道你为什么要构建自己的身份验证管理器。
所以让我们来完成这些步骤,当你选择使用formLogin时,框架会用你提供的bean创建一个认证管理器。你已经提供了一个passwordEncoder,你还应该提供一个UserDetailsService接口的实现。这应该像一个bean一样提供:

@Bean
CustomUserDetailsService customUserDetailsService() {
    return new CustomUserDetailsService();
}

然后Spring将创建一个DaoAuthenticationProvider,并将您的密码编码器和您的自定义UserDetailsService粘贴在其中。
您的错误消息告诉我,由于您已经构建了一个泛型提供程序,框架无法向其添加更多内容。
您应该阅读文档FormLogin Spring security中的如何启用表单登录
基本上去除了:

@Bean
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder builder) throws Exception {
    return builder.userDetailsService(userDetailsService)
                  .passwordEncoder(passwordEncoder())
                  .and()
                  .build();
}

相关问题