Pick Up SecurityContextHolderStrategy Bean
This commit provides the SecurityContextHolderStrategy bean to ProviderManager instances that the HttpSecurity DSL constructs. Issue gh-17862
This commit is contained in:
		
							parent
							
								
									8468c6a805
								
							
						
					
					
						commit
						44fef786aa
					
				|  | @ -18,10 +18,14 @@ package org.springframework.security.config.annotation.authentication.builders; | |||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.stream.Stream; | ||||
| 
 | ||||
| import org.apache.commons.logging.Log; | ||||
| import org.apache.commons.logging.LogFactory; | ||||
| import org.jspecify.annotations.Nullable; | ||||
| 
 | ||||
| import org.springframework.beans.factory.BeanFactory; | ||||
| import org.springframework.beans.factory.ObjectProvider; | ||||
| import org.springframework.security.authentication.AuthenticationEventPublisher; | ||||
| import org.springframework.security.authentication.AuthenticationManager; | ||||
| import org.springframework.security.authentication.AuthenticationProvider; | ||||
|  | @ -37,6 +41,8 @@ import org.springframework.security.config.annotation.authentication.configurers | |||
| import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer; | ||||
| import org.springframework.security.config.annotation.authentication.configurers.userdetails.UserDetailsAwareConfigurer; | ||||
| import org.springframework.security.core.Authentication; | ||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||
| import org.springframework.security.core.context.SecurityContextHolderStrategy; | ||||
| import org.springframework.security.core.userdetails.UserDetailsService; | ||||
| import org.springframework.util.Assert; | ||||
| 
 | ||||
|  | @ -235,6 +241,10 @@ public class AuthenticationManagerBuilder | |||
| 		if (this.eventPublisher != null) { | ||||
| 			providerManager.setAuthenticationEventPublisher(this.eventPublisher); | ||||
| 		} | ||||
| 		SecurityContextHolderStrategy securityContextHolderStrategy = getBeanProvider( | ||||
| 				SecurityContextHolderStrategy.class) | ||||
| 			.getIfUnique(SecurityContextHolder::getContextHolderStrategy); | ||||
| 		providerManager.setSecurityContextHolderStrategy(securityContextHolderStrategy); | ||||
| 		providerManager = postProcess(providerManager); | ||||
| 		return providerManager; | ||||
| 	} | ||||
|  | @ -283,4 +293,24 @@ public class AuthenticationManagerBuilder | |||
| 		return configurer; | ||||
| 	} | ||||
| 
 | ||||
| 	private <C> ObjectProvider<C> getBeanProvider(Class<C> clazz) { | ||||
| 		BeanFactory beanFactory = getSharedObject(BeanFactory.class); | ||||
| 		return (beanFactory != null) ? beanFactory.getBeanProvider(clazz) : new SingleObjectProvider<>(null); | ||||
| 	} | ||||
| 
 | ||||
| 	private static final class SingleObjectProvider<O> implements ObjectProvider<O> { | ||||
| 
 | ||||
| 		private final @Nullable O object; | ||||
| 
 | ||||
| 		private SingleObjectProvider(@Nullable O object) { | ||||
| 			this.object = object; | ||||
| 		} | ||||
| 
 | ||||
| 		@Override | ||||
| 		public Stream<O> stream() { | ||||
| 			return Stream.ofNullable(this.object); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; | |||
| 
 | ||||
| import org.springframework.aop.framework.ProxyFactoryBean; | ||||
| import org.springframework.aop.target.LazyInitTargetSource; | ||||
| import org.springframework.beans.factory.BeanFactory; | ||||
| import org.springframework.beans.factory.BeanFactoryUtils; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.context.ApplicationContext; | ||||
|  | @ -83,6 +84,7 @@ public class AuthenticationConfiguration { | |||
| 		AuthenticationEventPublisher authenticationEventPublisher = getAuthenticationEventPublisher(context); | ||||
| 		DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder( | ||||
| 				objectPostProcessor, defaultPasswordEncoder); | ||||
| 		result.setSharedObject(BeanFactory.class, this.applicationContext); | ||||
| 		if (authenticationEventPublisher != null) { | ||||
| 			result.authenticationEventPublisher(authenticationEventPublisher); | ||||
| 		} | ||||
|  |  | |||
|  | @ -318,6 +318,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit | |||
| 				.postProcess(new DefaultAuthenticationEventPublisher()); | ||||
| 			this.auth = new AuthenticationManagerBuilder(this.objectPostProcessor); | ||||
| 			this.auth.authenticationEventPublisher(eventPublisher); | ||||
| 			this.auth.setSharedObject(BeanFactory.class, this.context); | ||||
| 			configure(this.auth); | ||||
| 			this.authenticationManager = (this.disableAuthenticationRegistry) | ||||
| 					? getAuthenticationConfiguration().getAuthenticationManager() : this.auth.build(); | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import java.util.HashMap; | |||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.springframework.beans.factory.BeanFactory; | ||||
| import org.springframework.beans.factory.ObjectProvider; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.context.ApplicationContext; | ||||
|  | @ -116,6 +117,7 @@ class HttpSecurityConfiguration { | |||
| 		LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context); | ||||
| 		AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder( | ||||
| 				this.objectPostProcessor, passwordEncoder); | ||||
| 		authenticationBuilder.setSharedObject(BeanFactory.class, this.context); | ||||
| 		authenticationBuilder.parentAuthenticationManager(authenticationManager()); | ||||
| 		authenticationBuilder.authenticationEventPublisher(getAuthenticationEventPublisher()); | ||||
| 		HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects()); | ||||
|  |  | |||
|  | @ -162,8 +162,10 @@ public class WebAuthnConfigurer<H extends HttpSecurityBuilder<H>> | |||
| 		WebAuthnRelyingPartyOperations rpOperations = webAuthnRelyingPartyOperations(userEntities, userCredentials); | ||||
| 		PublicKeyCredentialCreationOptionsRepository creationOptionsRepository = creationOptionsRepository(); | ||||
| 		WebAuthnAuthenticationFilter webAuthnAuthnFilter = new WebAuthnAuthenticationFilter(); | ||||
| 		webAuthnAuthnFilter.setAuthenticationManager( | ||||
| 				new ProviderManager(new WebAuthnAuthenticationProvider(rpOperations, userDetailsService))); | ||||
| 		ProviderManager manager = new ProviderManager( | ||||
| 				new WebAuthnAuthenticationProvider(rpOperations, userDetailsService)); | ||||
| 		manager.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy()); | ||||
| 		webAuthnAuthnFilter.setAuthenticationManager(manager); | ||||
| 		WebAuthnRegistrationFilter webAuthnRegistrationFilter = new WebAuthnRegistrationFilter(userCredentials, | ||||
| 				rpOperations); | ||||
| 		PublicKeyCredentialCreationOptionsFilter creationOptionsFilter = new PublicKeyCredentialCreationOptionsFilter( | ||||
|  |  | |||
|  | @ -30,6 +30,8 @@ import org.springframework.security.authentication.ObservationAuthenticationMana | |||
| import org.springframework.security.authentication.ProviderManager; | ||||
| import org.springframework.security.authentication.dao.DaoAuthenticationProvider; | ||||
| import org.springframework.security.config.BeanIds; | ||||
| import org.springframework.security.core.context.SecurityContextHolder; | ||||
| import org.springframework.security.core.context.SecurityContextHolderStrategy; | ||||
| import org.springframework.security.core.userdetails.UserDetailsService; | ||||
| import org.springframework.security.crypto.password.PasswordEncoder; | ||||
| 
 | ||||
|  | @ -72,6 +74,10 @@ public class AuthenticationManagerFactoryBean implements FactoryBean<Authenticat | |||
| 			} | ||||
| 			provider.afterPropertiesSet(); | ||||
| 			ProviderManager manager = new ProviderManager(Arrays.asList(provider)); | ||||
| 			SecurityContextHolderStrategy securityContextHolderStrategy = this.bf | ||||
| 				.getBeanProvider(SecurityContextHolderStrategy.class) | ||||
| 				.getIfUnique(SecurityContextHolder::getContextHolderStrategy); | ||||
| 			manager.setSecurityContextHolderStrategy(securityContextHolderStrategy); | ||||
| 			if (this.observationRegistry.isNoop()) { | ||||
| 				return manager; | ||||
| 			} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue