使用Spring Security配置多个HttpSecurity示例时出现AlreadyBuiltException

2ledvvac  于 2023-08-02  发布在  Spring
关注(0)|答案(1)|浏览(113)

我正在使用Spring v.5.3.28和Spring Security v.5.8.4,并且我试图在不扩展WebSecurityConfigurerAdapter的情况下配置Spring Security,因为它已被弃用。
我的Spring Security配置看起来像这样:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {

    private static final String SIGNIN = "/signin";

    @Autowired
    ApiCustomAuthenticationProviderImpl apiCustomAuthenticationProvider;

    @Autowired
    CustomAuthenticationProviderImpl customAuthenticationProvider;

    @Autowired
    LdapAuthenticationProviderImpl ldapAuthenticationProvider;

    @Autowired
    SautenticaAuthenticationProviderImpl sautenticaAuthenticationProvider;

    @Autowired
    ConfigurationService configurationService;

    @Bean
    protected UserDetailsService userDetailsService () {
        return new AutenticacionServiceImpl();
    }

    @Bean
    public EvaluationContextExtension securityExtension () {
        return new SecurityEvaluationContextExtension();
    }

    @Bean
    public AuditorAware<Usuario> auditorAware () {
        return new SpringSecurityAuditorAware();
    }

    public AuthenticationManager getAuthenticationManager (HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);

        final String authMode = configurationService.findByCode(Constants.CT_AUTH_MODE);

        if (StringUtils.isNotEmpty(authMode) && Constants.CT_LDAP.equalsIgnoreCase(authMode)) {
            authenticationManagerBuilder.authenticationProvider(ldapAuthenticationProvider);
        } else if (StringUtils.isNotEmpty(authMode) && Constants.CT_SAUTENTICA.equalsIgnoreCase(authMode)) {
            authenticationManagerBuilder.authenticationProvider(sautenticaAuthenticationProvider);
        } else {
            authenticationManagerBuilder.authenticationProvider(customAuthenticationProvider);
        }

        authenticationManagerBuilder.eraseCredentials(false);

        return authenticationManagerBuilder.build();
    }

    @Bean
    @Order(1)
    public SecurityFilterChain apiSecurityFilterChain (HttpSecurity http) throws Exception {
        try {
            http.securityMatcher("/api-ws/**");
            http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            http.authorizeHttpRequests().requestMatchers("/api-ws/**").authenticated().and().httpBasic().and().csrf().disable()
                    .addFilterAfter(new ApiCustomBasicAuthenticationFilter(), BasicAuthenticationFilter.class);
            http.authenticationProvider(apiCustomAuthenticationProvider);

        } catch (final Exception e) {
            throw new SecurityException(e);
        }
        return http.build();
    }

    @Bean
    @Order(2)
    public SecurityFilterChain wsSecurityFilterChain (HttpSecurity http) throws Exception {
        try {
            http.securityMatcher("/ws/**");
            http.authorizeHttpRequests().requestMatchers("/ws/patient/**", "/meet-ws/case/**").authenticated();
            http.httpBasic().and().addFilterAt(new CustomBasicAuthenticationFilter(getAuthenticationManager(http)), BasicAuthenticationFilter.class);
            http.headers().frameOptions().disable();
        } catch (final Exception e) {
            throw new SecurityException(e);
        }
        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer () {
        return web -> web.ignoring().requestMatchers("/ws/login**", "/ws/new/xml**");
    }

    @Bean
    public SecurityFilterChain securityFilterChain (HttpSecurity http) throws Exception {

        try {
            http.authorizeHttpRequests().requestMatchers("/favicon.ico", "/resources/**", "/health**", "/signin**", "/authenticate**").permitAll().anyRequest().authenticated()
                    .and().authenticationManager(getAuthenticationManager(http)).formLogin().loginPage(SIGNIN).permitAll().loginProcessingUrl("/authenticate").permitAll()
                    .failureUrl("/signin?error=1").successHandler(new CustomAuthenticationSuccessHandler()).and().sessionManagement().invalidSessionUrl(SIGNIN).and()
                    .exceptionHandling().accessDeniedHandler(new AccessDeniedHandler()).and().headers().frameOptions().disable();

            http.logout().logoutUrl("/logout").logoutSuccessUrl(SIGNIN).permitAll();
        
        } catch (final Exception e) {
            throw new SecurityException(e);
        }
        return http.build();
    }

}

字符串
当我构建项目时,它会成功构建,但当我启动服务器时,它会抛出以下异常:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wsSecurityFilterChain' defined in es.mycompany.myapp.SecurityConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'wsSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:768)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:720)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:920)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:399)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:278)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4766)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5230)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:263)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:432)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:927)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:772)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wsSecurityFilterChain' defined in es.mycompany.myapp.SecurityConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'wsSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1609)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1573)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1462)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1349)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:760)
    ... 46 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'wsSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
    ... 62 more
Caused by: org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:41)
    at org.springframework.security.config.annotation.web.builders.HttpSecurity.beforeConfigure(HttpSecurity.java:3225)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:308)
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38)
    at es.mycompany.myapp.SecurityConfiguration.wsSecurityFilterChain(SecurityConfiguration.java:152)
    at es.mycompany.myapp.SecurityConfiguration$$EnhancerBySpringCGLIB$$aaa83f30.CGLIB$wsSecurityFilterChain$7(<generated>)
    at es.mycompany.myapp.SecurityConfiguration$$EnhancerBySpringCGLIB$$aaa83f30$$FastClassBySpringCGLIB$$ed15352b.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
    at es.mycompany.myapp.SecurityConfiguration$$EnhancerBySpringCGLIB$$aaa83f30.wsSecurityFilterChain(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 63 more


我唯一能想到的是http.build();被调用了两次,但它们在文档中做了完全相同的事情:https://docs.spring.io/spring-security/reference/servlet/configuration/java.html#_multiple_httpsecurity_instances

zpqajqem

zpqajqem1#

您收到的错误来自您自己调用authenticationManagerBuilder.build()。您正在访问构建器的内部框架示例并自己调用build(),而Spring Security也在内部构建身份验证管理器。
通常,任何AuthenticationProvider@Bean(或@Component等)将由Spring Security自动连接。您可能希望重新构造应用程序,以便有条件地将所需的AuthenticationProvider应用到相关的过滤器链(而不是作为bean发布)。应该删除整个getAuthenticationManager方法。

相关问题