Delay initialization UserDetailsService in Global Authentication

This commit is contained in:
DingHao 2024-11-22 07:38:44 +08:00 committed by Josh Cummings
parent 0f85da77be
commit ef7b11ac01

View File

@ -16,8 +16,7 @@
package org.springframework.security.config.annotation.authentication.configuration; package org.springframework.security.config.annotation.authentication.configuration;
import java.util.ArrayList; import java.util.Arrays;
import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -66,9 +65,10 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
@Override @Override
public void configure(AuthenticationManagerBuilder auth) throws Exception { public void configure(AuthenticationManagerBuilder auth) throws Exception {
List<BeanWithName<UserDetailsService>> userDetailsServices = getBeansWithName(UserDetailsService.class); String[] beanNames = InitializeUserDetailsBeanManagerConfigurer.this.context
.getBeanNamesForType(UserDetailsService.class);
if (auth.isConfigured()) { if (auth.isConfigured()) {
if (!userDetailsServices.isEmpty()) { if (beanNames.length > 0) {
this.logger.warn("Global AuthenticationManager configured with an AuthenticationProvider bean. " this.logger.warn("Global AuthenticationManager configured with an AuthenticationProvider bean. "
+ "UserDetailsService beans will not be used for username/password login. " + "UserDetailsService beans will not be used for username/password login. "
+ "Consider removing the AuthenticationProvider bean. " + "Consider removing the AuthenticationProvider bean. "
@ -78,19 +78,18 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
return; return;
} }
if (userDetailsServices.isEmpty()) { if (beanNames.length == 0) {
return; return;
} }
else if (userDetailsServices.size() > 1) { else if (beanNames.length > 1) {
List<String> beanNames = userDetailsServices.stream().map(BeanWithName::getName).toList();
this.logger.warn(LogMessage.format("Found %s UserDetailsService beans, with names %s. " this.logger.warn(LogMessage.format("Found %s UserDetailsService beans, with names %s. "
+ "Global Authentication Manager will not use a UserDetailsService for username/password login. " + "Global Authentication Manager will not use a UserDetailsService for username/password login. "
+ "Consider publishing a single UserDetailsService bean.", userDetailsServices.size(), + "Consider publishing a single UserDetailsService bean.", beanNames.length,
beanNames)); Arrays.toString(beanNames)));
return; return;
} }
UserDetailsService userDetailsService = userDetailsServices.get(0).getBean(); UserDetailsService userDetailsService = InitializeUserDetailsBeanManagerConfigurer.this.context
String userDetailsServiceBeanName = userDetailsServices.get(0).getName(); .getBean(beanNames[0], UserDetailsService.class);
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class); PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class); UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
CompromisedPasswordChecker passwordChecker = getBeanOrNull(CompromisedPasswordChecker.class); CompromisedPasswordChecker passwordChecker = getBeanOrNull(CompromisedPasswordChecker.class);
@ -111,8 +110,7 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
provider.afterPropertiesSet(); provider.afterPropertiesSet();
auth.authenticationProvider(provider); auth.authenticationProvider(provider);
this.logger.info(LogMessage.format( this.logger.info(LogMessage.format(
"Global AuthenticationManager configured with UserDetailsService bean with name %s", "Global AuthenticationManager configured with UserDetailsService bean with name %s", beanNames[0]));
userDetailsServiceBeanName));
} }
/** /**
@ -127,41 +125,6 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
return InitializeUserDetailsBeanManagerConfigurer.this.context.getBean(beanNames[0], type); return InitializeUserDetailsBeanManagerConfigurer.this.context.getBean(beanNames[0], type);
} }
/**
* @return a list of beans of the requested class, along with their names. If
* there are no registered beans of that type, the list is empty.
*/
private <T> List<BeanWithName<T>> getBeansWithName(Class<T> type) {
List<BeanWithName<T>> beanWithNames = new ArrayList<>();
String[] beanNames = InitializeUserDetailsBeanManagerConfigurer.this.context.getBeanNamesForType(type);
for (String beanName : beanNames) {
T bean = InitializeUserDetailsBeanManagerConfigurer.this.context.getBean(beanName, type);
beanWithNames.add(new BeanWithName<T>(bean, beanName));
}
return beanWithNames;
}
static class BeanWithName<T> {
private final T bean;
private final String name;
BeanWithName(T bean, String name) {
this.bean = bean;
this.name = name;
}
T getBean() {
return this.bean;
}
String getName() {
return this.name;
}
}
} }
} }