【问题标题】:Spring Boot with mulitple authentication profiles具有多个身份验证配置文件的 Spring Boot
【发布时间】:2021-07-09 05:10:19
【问题描述】:

我按照这两篇文章在 Spring Boot 应用程序中实现了多个身份验证配置文件:

最终的SecurityConfiguration 类如下所示:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Configuration
    @Profile({"qa", "prod"})
    public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf()
                    .disable()
                    .authorizeRequests()
                    .antMatchers("/someUrl").permitAll()
                    .antMatchers("/someUrl").fullyAuthenticated()
                    .antMatchers("/api/ping").permitAll()
                    .antMatchers("/**").fullyAuthenticated()
                    
                    ...
                    .

        }
    }

    @Configuration
    public static class LocalSecurityConfiguration extends WebSecurityConfigurerAdapter {
...

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

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf()
                    .disable()
                    .authorizeRequests()
                    .antMatchers("/someUrl").permitAll()
                    .antMatchers("/someUrl").fullyAuthenticated()
                    .antMatchers("/api/ping").permitAll()
                    .antMatchers("/**").permitAll().
                    ...
                    .

        }
    }
}

对于qaprod 配置文件(环境),我还有单独的application-{profile}.yaml 文件。

当启动应用程序时

mvn spring-boot:run -Dspring.profiles.active=qa

我看到应用了正确的配置文件 (qa):

Running with Spring Boot v2.1.3.RELEASE, Spring v5.1.5.RELEASE
...
 The following profiles are active: a
...

但后来失败了:

***************************
APPLICATION FAILED TO START
***************************

Description:

The bean 'authenticationManagerBean', defined in class path resource [com/.../SecurityConfiguration$WebSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/../SecurityConfiguration$LocalSecurityConfiguration.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

[WARNING] 
java.lang.reflect.InvocationTargetException
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:558)
    at java.lang.Thread.run (Thread.java:834)
Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'authenticationManagerBean' defined in class path resource [com/../SecurityConfiguration$WebSecurityConfiguration.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=securityConfiguration.WebSecurityConfiguration; factoryMethodName=authenticationManagerBean; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/.../SecurityConfiguration$WebSecurityConfiguration.class]] for bean 'authenticationManagerBean': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=securityConfiguration.LocalSecurityConfiguration; factoryMethodName=authenticationManagerBean; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/..../SecurityConfiguration$LocalSecurityConfiguration.class]] bound.

在不指定任何配置文件的情况下运行时,它启动时不会出现错误。 这有什么问题?

谢谢。

【问题讨论】:

  • 你没有自定义 authenticationManager,所以我看不出你为什么需要用它创建一个 bean?,我建议你尝试删除 authenticationManager 函数上方的 @Bean 定义.
  • 你同时暴露了AuthenticationManager的两个bean。这应该是个问题。 LocalSecurityConfiguration 始终执行,另外WebSecurityConfiguration 用于配置文件。

标签: spring-boot spring-security


【解决方案1】:

据我了解,当您启用 qa 配置文件时,WebSecurityConfiguration 类型的两个 bean 都处于活动状态,因此 Spring 无法同时启用它们,这就是您遇到错误的原因。当您在没有配置文件的情况下运行它时,WebSecurityConfiguration 未启用,因此只有一个 WebSecurityConfigurerAdapter 类型的 bean 处于活动状态。一种解决方案是注释 LocalSecurityConfiguration bean 带有否定条件,例如

@Profile("!qa & !prod")

这适用于 Spring 版本 > 5.1 (Spring Boot 2.1),在以前的版本中,您可以使用 @Conditional 注释 (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Conditional.html) 并创建自定义实现来表达您的逻辑扩展 SpringBootCondition

【讨论】:

  • 正确的语法是否应该像@Profile({"!qa & !prod"})那样使用大括号?
  • 你是对的,Profiles 接口中 value 的数据类型是 String [] 所以使用大括号就可以了。但如果您想指定一个值,则不是强制性的。 Java 语言规范:If the element type is an array type, then it is not required to use curly braces to specify the element value of the element-value pair. If the element value is not an ElementValueArrayInitializer, then an array value whose sole element is the element value is associated with the element 这意味着如果您指定一个字符串而不是数组,则将创建一个只有一个元素的数组
【解决方案2】:

您是否尝试过日志中建议的操作?

考虑重命名其中一个 bean 或通过设置启用覆盖

spring.main.allow-bean-definition-overriding=true

您可以在此处找到相关答案。它可能会有所帮助。 SpringBoot - BeanDefinitionOverrideException: Invalid bean definition

这是另一个来自 baeldung 的建议帖子 https://www.baeldung.com/spring-boot-bean-definition-override-exception

【讨论】:

    猜你喜欢
    • 2018-01-29
    • 2022-11-04
    • 2015-06-20
    • 1970-01-01
    • 2016-10-21
    • 2021-08-17
    • 1970-01-01
    • 2019-01-24
    相关资源
    最近更新 更多