From 91ef7ce1cffc558f8c4b73f7a6a4b9c173846d63 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Thu, 18 Jan 2018 08:59:27 -0600 Subject: [PATCH] AuthenticationEventPublisher Bean used by Default Fixes: gh-4940 --- .../AuthenticationConfiguration.java | 27 +++--- ...thenticationConfigurationPublishTests.java | 84 +++++++++++++++++++ .../AuthenticationTestConfiguration.java | 35 ++++++++ 3 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java create mode 100644 config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java index 114ed470a2..1a1e9b0260 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java @@ -34,6 +34,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -76,7 +77,13 @@ public class AuthenticationConfiguration { public AuthenticationManagerBuilder authenticationManagerBuilder( ObjectPostProcessor objectPostProcessor, ApplicationContext context) { LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context); - return new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder); + AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context, AuthenticationEventPublisher.class); + + DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder); + if (authenticationEventPublisher != null) { + result.authenticationEventPublisher(authenticationEventPublisher); + } + return result; } @Bean @@ -159,6 +166,14 @@ public class AuthenticationConfiguration { return lazyBean(AuthenticationManager.class); } + private static T getBeanOrNull(ApplicationContext applicationContext, Class type) { + try { + return applicationContext.getBean(type); + } catch(NoSuchBeanDefinitionException notFound) { + return null; + } + } + private static class EnableGlobalAuthenticationAutowiredConfigurer extends GlobalAuthenticationConfigurerAdapter { private final ApplicationContext context; @@ -278,7 +293,7 @@ public class AuthenticationConfiguration { if (this.passwordEncoder != null) { return this.passwordEncoder; } - PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class); + PasswordEncoder passwordEncoder = getBeanOrNull(this.applicationContext, PasswordEncoder.class); if (passwordEncoder == null) { passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @@ -286,14 +301,6 @@ public class AuthenticationConfiguration { return passwordEncoder; } - private T getBeanOrNull(Class type) { - try { - return this.applicationContext.getBean(type); - } catch(NoSuchBeanDefinitionException notFound) { - return null; - } - } - @Override public String toString() { return getPasswordEncoder().toString(); diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java new file mode 100644 index 0000000000..b3100fc023 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.authentication.configuration; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.security.authentication.AuthenticationEventPublisher; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.event.AuthenticationSuccessEvent; +import org.springframework.security.config.users.AuthenticationTestConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +/** + * @author Rob Winch + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class AuthenticationConfigurationPublishTests { + @Autowired + MockEventListener listener; + + AuthenticationManager authenticationManager; + + // gh-4940 + @Test + public void authenticationEventPublisherBeanUsedByDefault() { + this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + + assertThat(this.listener.events).hasSize(1); + } + + @Autowired + public void setAuthenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { + this.authenticationManager = authenticationConfiguration.getAuthenticationManager(); + } + + @EnableGlobalAuthentication + @Import(AuthenticationTestConfiguration.class) + static class Config { + @Bean + AuthenticationEventPublisher publisher() { + return new DefaultAuthenticationEventPublisher(); + } + + @Bean + MockEventListener eventListener() { + return new MockEventListener(); + } + } + + static class MockEventListener implements + ApplicationListener { + List events = new ArrayList<>(); + + public void onApplicationEvent(AuthenticationSuccessEvent event) { + this.events.add(event); + } + + } +} diff --git a/config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java b/config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java new file mode 100644 index 0000000000..9ebd0a46d1 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java @@ -0,0 +1,35 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.users; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.userdetails.PasswordEncodedUser; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; + +/** + * @author Rob Winch + * @since 5.0 + */ +@Configuration +public class AuthenticationTestConfiguration { + @Bean + public static UserDetailsService userDetailsService() { + return new InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin()); + } +}