diff --git a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java index 57342c9c81..49593ee13e 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +52,8 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition private static final String ATT_REF = "ref"; private static final String ATT_ERASE_CREDENTIALS = "erase-credentials"; + private static final String AUTHENTICATION_EVENT_PUBLISHER_BEAN_NAME = "defaultAuthenticationEventPublisher"; + public BeanDefinition parse(Element element, ParserContext pc) { String id = element.getAttribute("id"); @@ -124,12 +126,14 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition false); } - // Add the default event publisher - BeanDefinition publisher = new RootBeanDefinition( - DefaultAuthenticationEventPublisher.class); - String pubId = pc.getReaderContext().generateBeanName(publisher); - pc.registerBeanComponent(new BeanComponentDefinition(publisher, pubId)); - providerManagerBldr.addPropertyReference("authenticationEventPublisher", pubId); + if (!pc.getRegistry().containsBeanDefinition(AUTHENTICATION_EVENT_PUBLISHER_BEAN_NAME)) { + // Add the default event publisher to the context + BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class); + pc.registerBeanComponent(new BeanComponentDefinition(publisher, AUTHENTICATION_EVENT_PUBLISHER_BEAN_NAME)); + } + + providerManagerBldr.addPropertyReference("authenticationEventPublisher", + AUTHENTICATION_EVENT_PUBLISHER_BEAN_NAME); pc.registerBeanComponent(new BeanComponentDefinition(providerManagerBldr .getBeanDefinition(), id)); diff --git a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java index 6d64ca25eb..2081f26613 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; import org.springframework.security.authentication.ProviderManager; @@ -49,6 +50,18 @@ public class AuthenticationManagerBeanDefinitionParserTests { + " " + " " + ""; + + // Issue #7282 + // @formatter:off + private static final String CONTEXT_MULTI = "" + + " " + + " " + + " " + + " " + + " " + + ""; + // @formatter:on + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -60,6 +73,18 @@ public class AuthenticationManagerBeanDefinitionParserTests { assertThat(context.getBeansOfType(AuthenticationProvider.class)).hasSize(1); } + @Test + public void eventPublishersAreRegisteredAsTopLevelBeans() { + ConfigurableApplicationContext context = this.spring.context(CONTEXT).getContext(); + assertThat(context.getBeansOfType(AuthenticationEventPublisher.class)).hasSize(1); + } + + @Test + public void onlyOneEventPublisherIsRegisteredForMultipleAuthenticationManagers() { + ConfigurableApplicationContext context = this.spring.context(CONTEXT + '\n' + CONTEXT_MULTI).getContext(); + assertThat(context.getBeansOfType(AuthenticationEventPublisher.class)).hasSize(1); + } + @Test public void eventsArePublishedByDefault() throws Exception { ConfigurableApplicationContext appContext = this.spring.context(CONTEXT)