2
0
Эх сурвалжийг харах

AuthenticationEventPublisher Bean Lookup

Issue gh-7793
Fixes gh-7515
Josh Cummings 5 жил өмнө
parent
commit
5579846263

+ 10 - 2
config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java

@@ -26,6 +26,7 @@ import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.springframework.aop.TargetSource;
 import org.springframework.aop.framework.Advised;
 import org.springframework.aop.target.LazyInitTargetSource;
@@ -36,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
 import org.springframework.core.annotation.Order;
 import org.springframework.core.io.support.SpringFactoriesLoader;
+import org.springframework.security.authentication.AuthenticationEventPublisher;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
@@ -194,8 +196,7 @@ public abstract class WebSecurityConfigurerAdapter implements
 			return http;
 		}
 
-		DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
-				.postProcess(new DefaultAuthenticationEventPublisher());
+		AuthenticationEventPublisher eventPublisher = getAuthenticationEventPublisher();
 		localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
 
 		AuthenticationManager authenticationManager = authenticationManager();
@@ -407,6 +408,13 @@ public abstract class WebSecurityConfigurerAdapter implements
 		this.authenticationConfiguration = authenticationConfiguration;
 	}
 
+	private AuthenticationEventPublisher getAuthenticationEventPublisher() {
+		if (this.context.getBeanNamesForType(AuthenticationEventPublisher.class).length > 0) {
+			return this.context.getBean(AuthenticationEventPublisher.class);
+		}
+		return this.objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
+	}
+
 	/**
 	 * Creates the shared objects
 	 *

+ 34 - 0
config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java

@@ -33,6 +33,7 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.annotation.AnnotationAwareOrderComparator;
 import org.springframework.core.annotation.Order;
+import org.springframework.security.authentication.AuthenticationEventPublisher;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
@@ -40,9 +41,11 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.PasswordEncodedUser;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.web.accept.ContentNegotiationStrategy;
@@ -51,8 +54,11 @@ import org.springframework.web.filter.OncePerRequestFilter;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.ThrowableAssert.catchThrowable;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -364,4 +370,32 @@ public class WebSecurityConfigurerAdapterTests {
 	@Order
 	static class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter {
 	}
+
+	// gh-7515
+	@Test
+	public void performWhenUsingAuthenticationEventPublisherBeanThenUses() throws Exception {
+		this.spring.register(CustomAuthenticationEventPublisherBean.class).autowire();
+
+		AuthenticationEventPublisher authenticationEventPublisher =
+				this.spring.getContext().getBean(AuthenticationEventPublisher.class);
+
+		this.mockMvc.perform(get("/")
+				.with(httpBasic("user", "password")));
+
+		verify(authenticationEventPublisher).publishAuthenticationSuccess(any(Authentication.class));
+	}
+
+	@EnableWebSecurity
+	static class CustomAuthenticationEventPublisherBean extends WebSecurityConfigurerAdapter {
+		@Bean
+		@Override
+		public UserDetailsService userDetailsService() {
+			return new InMemoryUserDetailsManager(PasswordEncodedUser.user());
+		}
+
+		@Bean
+		public AuthenticationEventPublisher authenticationEventPublisher() {
+			return mock(AuthenticationEventPublisher.class);
+		}
+	}
 }

+ 44 - 1
config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java

@@ -73,6 +73,7 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.authentication.AuthenticationEventPublisher;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.AuthenticationManagerResolver;
 import org.springframework.security.authentication.AuthenticationProvider;
@@ -88,6 +89,7 @@ import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
+import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
@@ -99,8 +101,8 @@ import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
 import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
 import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication;
 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
-import org.springframework.security.oauth2.server.resource.authentication.JwtIssuerAuthenticationManagerResolver;
 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+import org.springframework.security.oauth2.server.resource.authentication.JwtIssuerAuthenticationManagerResolver;
 import org.springframework.security.oauth2.server.resource.introspection.NimbusOpaqueTokenIntrospector;
 import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
 import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
@@ -1091,6 +1093,22 @@ public class OAuth2ResourceServerConfigurerTests {
 				.andExpect(invalidTokenHeader("algorithm"));
 	}
 
+	// gh-7793
+	@Test
+	public void requestWhenUsingCustomAuthenticationEventPublisherThenUses() throws Exception{
+		this.spring.register(CustomAuthenticationEventPublisher.class).autowire();
+
+		when(bean(JwtDecoder.class).decode(anyString()))
+				.thenThrow(new JwtException("problem"));
+
+		this.mvc.perform(get("/").with(bearerToken("token")));
+
+		verifyBean(AuthenticationEventPublisher.class)
+				.publishAuthenticationFailure(
+						any(OAuth2AuthenticationException.class),
+						any(Authentication.class));
+	}
+
 	@Test
 	public void getWhenCustomJwtAuthenticationManagerThenUsed() throws Exception {
 		this.spring.register(JwtAuthenticationManagerConfig.class, BasicController.class).autowire();
@@ -2015,6 +2033,31 @@ public class OAuth2ResourceServerConfigurerTests {
 		}
 	}
 
+	@EnableWebSecurity
+	static class CustomAuthenticationEventPublisher extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.oauth2ResourceServer()
+					.jwt();
+			// @formatter:on
+		}
+
+		@Bean
+		JwtDecoder jwtDecoder() {
+			return mock(JwtDecoder.class);
+		}
+
+		@Bean
+		AuthenticationEventPublisher authenticationEventPublisher() {
+			return mock(AuthenticationEventPublisher.class);
+		}
+	}
+
 	@EnableWebSecurity
 	static class OpaqueTokenConfig extends WebSecurityConfigurerAdapter {
 		@Override