Prechádzať zdrojové kódy

AuthenticationEventPublisher Bean used by Default

Fixes: gh-4940
Rob Winch 7 rokov pred
rodič
commit
91ef7ce1cf

+ 17 - 10
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<Object> 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> T getBeanOrNull(ApplicationContext applicationContext, Class<T> 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> T getBeanOrNull(Class<T> type) {
-			try {
-				return this.applicationContext.getBean(type);
-			} catch(NoSuchBeanDefinitionException notFound) {
-				return null;
-			}
-		}
-
 		@Override
 		public String toString() {
 			return getPasswordEncoder().toString();

+ 84 - 0
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<AuthenticationSuccessEvent> {
+		List<AuthenticationSuccessEvent> events = new ArrayList<>();
+
+		public void onApplicationEvent(AuthenticationSuccessEvent event) {
+			this.events.add(event);
+		}
+
+	}
+}

+ 35 - 0
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());
+	}
+}