瀏覽代碼

Move classpath checks to class member variable

Closes gh-11437
Marcus Da Coregio 2 年之前
父節點
當前提交
52ed165476
共有 13 個文件被更改,包括 134 次插入35 次删除
  1. 16 2
      config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java
  2. 8 2
      config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java
  3. 8 1
      config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java
  4. 8 3
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java
  5. 9 2
      config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java
  6. 6 2
      config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java
  7. 8 3
      config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java
  8. 9 3
      config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java
  9. 8 4
      config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java
  10. 9 2
      config/src/main/java/org/springframework/security/config/ldap/EmbeddedLdapServerContextSourceFactoryBean.java
  11. 14 4
      config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java
  12. 25 5
      core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java
  13. 6 2
      test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java

+ 16 - 2
config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java

@@ -61,6 +61,14 @@ import org.springframework.util.ClassUtils;
 public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuilder<B>>
 		extends SecurityConfigurerAdapter<AuthenticationManager, B> {
 
+	private static final String APACHEDS_CLASSNAME = "org.apache.directory.server.core.DefaultDirectoryService";
+
+	private static final String UNBOUNDID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
+
+	private static final boolean apacheDsPresent;
+
+	private static final boolean unboundIdPresent;
+
 	private String groupRoleAttribute = "cn";
 
 	private String groupSearchBase = "";
@@ -91,6 +99,12 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
 
 	private GrantedAuthoritiesMapper authoritiesMapper;
 
+	static {
+		ClassLoader classLoader = LdapAuthenticationProviderConfigurer.class.getClassLoader();
+		apacheDsPresent = ClassUtils.isPresent(APACHEDS_CLASSNAME, classLoader);
+		unboundIdPresent = ClassUtils.isPresent(UNBOUNDID_CLASSNAME, classLoader);
+	}
+
 	private LdapAuthenticationProvider build() throws Exception {
 		BaseLdapPathContextSource contextSource = getContextSource();
 		LdapAuthenticator ldapAuthenticator = createLdapAuthenticator(contextSource);
@@ -562,13 +576,13 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
 		}
 
 		private void startEmbeddedLdapServer() throws Exception {
-			if (ClassUtils.isPresent(APACHEDS_CLASSNAME, getClass().getClassLoader())) {
+			if (apacheDsPresent) {
 				ApacheDSContainer apacheDsContainer = new ApacheDSContainer(this.root, this.ldif);
 				apacheDsContainer.setPort(getPort());
 				postProcess(apacheDsContainer);
 				this.port = apacheDsContainer.getLocalPort();
 			}
-			else if (ClassUtils.isPresent(UNBOUNDID_CLASSNAME, getClass().getClassLoader())) {
+			else if (unboundIdPresent) {
 				UnboundIdContainer unboundIdContainer = new UnboundIdContainer(this.root, this.ldif);
 				unboundIdContainer.setPort(getPort());
 				postProcess(unboundIdContainer);

+ 8 - 2
config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java

@@ -51,12 +51,18 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 @Import(OAuth2ClientConfiguration.OAuth2ClientWebMvcImportSelector.class)
 final class OAuth2ClientConfiguration {
 
+	private static final boolean webMvcPresent;
+
+	static {
+		ClassLoader classLoader = OAuth2ClientConfiguration.class.getClassLoader();
+		webMvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", classLoader);
+	}
+
 	static class OAuth2ClientWebMvcImportSelector implements ImportSelector {
 
 		@Override
 		public String[] selectImports(AnnotationMetadata importingClassMetadata) {
-			if (!ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet",
-					getClass().getClassLoader())) {
+			if (!webMvcPresent) {
 				return new String[0];
 			}
 			return new String[] { "org.springframework.security.config.annotation.web.configuration."

+ 8 - 1
config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java

@@ -30,9 +30,16 @@ import org.springframework.util.ClassUtils;
  */
 class SpringWebMvcImportSelector implements ImportSelector {
 
+	private static final boolean webMvcPresent;
+
+	static {
+		ClassLoader classLoader = SpringWebMvcImportSelector.class.getClassLoader();
+		webMvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", classLoader);
+	}
+
 	@Override
 	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
-		if (!ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader())) {
+		if (!webMvcPresent) {
 			return new String[0];
 		}
 		return new String[] {

+ 8 - 3
config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java

@@ -40,14 +40,20 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
  */
 public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<CorsConfigurer<H>, H> {
 
-	private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
-
 	private static final String CORS_CONFIGURATION_SOURCE_BEAN_NAME = "corsConfigurationSource";
 
 	private static final String CORS_FILTER_BEAN_NAME = "corsFilter";
 
+	private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
+
+	private static final boolean mvcPresent;
+
 	private CorsConfigurationSource configurationSource;
 
+	static {
+		mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, CorsConfigurer.class.getClassLoader());
+	}
+
 	/**
 	 * Creates a new instance
 	 *
@@ -84,7 +90,6 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
 					CorsConfigurationSource.class);
 			return new CorsFilter(configurationSource);
 		}
-		boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, context.getClassLoader());
 		if (mvcPresent) {
 			return MvcCorsFilter.getMvcCorsFilter(context);
 		}

+ 9 - 2
config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java

@@ -47,10 +47,17 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve
  */
 final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
 
+	private static final boolean oauth2ClientPresent;
+
+	static {
+		oauth2ClientPresent = ClassUtils.isPresent(
+				"org.springframework.security.oauth2.client.registration.ClientRegistration",
+				ReactiveOAuth2ClientImportSelector.class.getClassLoader());
+	}
+
 	@Override
 	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
-		if (!ClassUtils.isPresent("org.springframework.security.oauth2.client.registration.ClientRegistration",
-				getClass().getClassLoader())) {
+		if (!oauth2ClientPresent) {
 			return new String[0];
 		}
 		return new String[] { "org.springframework.security.config.annotation.web.reactive."

+ 6 - 2
config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java

@@ -53,13 +53,17 @@ class WebFluxSecurityConfiguration {
 
 	public static final String REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME = "org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository";
 
-	private static final boolean isOAuth2Present = ClassUtils.isPresent(
-			REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME, WebFluxSecurityConfiguration.class.getClassLoader());
+	private static final boolean isOAuth2Present;
 
 	private List<SecurityWebFilterChain> securityWebFilterChains;
 
 	private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
 
+	static {
+		isOAuth2Present = ClassUtils.isPresent(REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME,
+				WebFluxSecurityConfiguration.class.getClassLoader());
+	}
+
 	@Autowired
 	ApplicationContext context;
 

+ 8 - 3
config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java

@@ -80,6 +80,8 @@ final class AuthenticationConfigBuilder {
 
 	private final Log logger = LogFactory.getLog(getClass());
 
+	private static final boolean webMvcPresent;
+
 	private static final String ATT_REALM = "realm";
 
 	private static final String DEF_REALM = "Realm";
@@ -213,6 +215,11 @@ final class AuthenticationConfigBuilder {
 
 	private final List<BeanDefinition> csrfIgnoreRequestMatchers = new ManagedList<>();
 
+	static {
+		ClassLoader classLoader = AuthenticationConfigBuilder.class.getClassLoader();
+		webMvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", classLoader);
+	}
+
 	AuthenticationConfigBuilder(Element element, boolean forceAutoConfig, ParserContext pc,
 			SessionCreationPolicy sessionPolicy, BeanReference requestCache, BeanReference authenticationManager,
 			BeanMetadataElement authenticationFilterSecurityContextHolderStrategyRef,
@@ -409,9 +416,7 @@ final class AuthenticationConfigBuilder {
 		if (!this.oauth2LoginEnabled && !this.oauth2ClientEnabled) {
 			return;
 		}
-		boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet",
-				getClass().getClassLoader());
-		if (webmvcPresent) {
+		if (webMvcPresent) {
 			this.pc.getReaderContext()
 					.registerWithGeneratedName(new RootBeanDefinition(OAuth2ClientWebMvcSecurityPostProcessor.class));
 		}

+ 9 - 3
config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java

@@ -36,12 +36,19 @@ import org.springframework.web.filter.CorsFilter;
  */
 public class CorsBeanDefinitionParser {
 
-	private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
-
 	private static final String ATT_SOURCE = "configuration-source-ref";
 
 	private static final String ATT_REF = "ref";
 
+	private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
+
+	private static final boolean mvcPresent;
+
+	static {
+		mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
+				CorsBeanDefinitionParser.class.getClassLoader());
+	}
+
 	public BeanMetadataElement parse(Element element, ParserContext parserContext) {
 		if (element == null) {
 			return null;
@@ -64,7 +71,6 @@ public class CorsBeanDefinitionParser {
 		if (StringUtils.hasText(configurationSourceRef)) {
 			return new RuntimeBeanReference(configurationSourceRef);
 		}
-		boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, getClass().getClassLoader());
 		if (!mvcPresent) {
 			return null;
 		}

+ 8 - 4
config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java

@@ -66,14 +66,19 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
 
 	private static final String REQUEST_DATA_VALUE_PROCESSOR = "requestDataValueProcessor";
 
-	private static final String DISPATCHER_SERVLET_CLASS_NAME = "org.springframework.web.servlet.DispatcherServlet";
-
 	private static final String ATT_MATCHER = "request-matcher-ref";
 
 	private static final String ATT_REPOSITORY = "token-repository-ref";
 
 	private static final String ATT_REQUEST_HANDLER = "request-handler-ref";
 
+	private static final boolean webMvcPresent;
+
+	static {
+		ClassLoader classLoader = CsrfBeanDefinitionParser.class.getClassLoader();
+		webMvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", classLoader);
+	}
+
 	private String csrfRepositoryRef;
 
 	private BeanDefinition csrfFilter;
@@ -90,8 +95,7 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
 		if (disabled) {
 			return null;
 		}
-		boolean webmvcPresent = ClassUtils.isPresent(DISPATCHER_SERVLET_CLASS_NAME, getClass().getClassLoader());
-		if (webmvcPresent) {
+		if (webMvcPresent) {
 			if (!pc.getRegistry().containsBeanDefinition(REQUEST_DATA_VALUE_PROCESSOR)) {
 				RootBeanDefinition beanDefinition = new RootBeanDefinition(CsrfRequestDataValueProcessor.class);
 				BeanComponentDefinition componentDefinition = new BeanComponentDefinition(beanDefinition,

+ 9 - 2
config/src/main/java/org/springframework/security/config/ldap/EmbeddedLdapServerContextSourceFactoryBean.java

@@ -42,6 +42,8 @@ public class EmbeddedLdapServerContextSourceFactoryBean
 
 	private static final String UNBOUNDID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
 
+	private static final boolean unboundIdPresent;
+
 	private static final int DEFAULT_PORT = 33389;
 
 	private static final int RANDOM_PORT = 0;
@@ -60,6 +62,11 @@ public class EmbeddedLdapServerContextSourceFactoryBean
 
 	private EmbeddedLdapServerContainer container;
 
+	static {
+		ClassLoader classLoader = EmbeddedLdapServerContextSourceFactoryBean.class.getClassLoader();
+		unboundIdPresent = ClassUtils.isPresent(UNBOUNDID_CLASSNAME, classLoader);
+	}
+
 	/**
 	 * Create an EmbeddedLdapServerContextSourceFactoryBean that will use an embedded LDAP
 	 * server to perform LDAP authentication. This requires a dependency on
@@ -120,7 +127,7 @@ public class EmbeddedLdapServerContextSourceFactoryBean
 
 	@Override
 	public DefaultSpringSecurityContextSource getObject() throws Exception {
-		if (!ClassUtils.isPresent(UNBOUNDID_CLASSNAME, getClass().getClassLoader())) {
+		if (!unboundIdPresent) {
 			throw new IllegalStateException("Embedded LDAP server is not provided");
 		}
 		this.container = getContainer();
@@ -156,7 +163,7 @@ public class EmbeddedLdapServerContextSourceFactoryBean
 	}
 
 	private EmbeddedLdapServerContainer getContainer() {
-		if (!ClassUtils.isPresent(UNBOUNDID_CLASSNAME, getClass().getClassLoader())) {
+		if (!unboundIdPresent) {
 			throw new IllegalStateException("Embedded LDAP server is not provided");
 		}
 		UnboundIdContainer unboundIdContainer = new UnboundIdContainer(this.root, this.ldif);

+ 14 - 4
config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java

@@ -86,6 +86,16 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 
 	private static final String UNBOUNDID_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.UnboundIdContainer";
 
+	private static final boolean unboundIdPresent;
+
+	private static final boolean apacheDsPresent;
+
+	static {
+		ClassLoader classLoader = LdapServerBeanDefinitionParser.class.getClassLoader();
+		unboundIdPresent = ClassUtils.isPresent(UNBOUNID_CLASSNAME, classLoader);
+		apacheDsPresent = ClassUtils.isPresent(APACHEDS_CLASSNAME, classLoader);
+	}
+
 	@Override
 	public BeanDefinition parse(Element elt, ParserContext parserContext) {
 		String url = elt.getAttribute(ATT_URL);
@@ -184,11 +194,11 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 	}
 
 	private boolean isApacheDsEnabled(String mode) {
-		return "apacheds".equals(mode) || ClassUtils.isPresent(APACHEDS_CLASSNAME, getClass().getClassLoader());
+		return "apacheds".equals(mode) || apacheDsPresent;
 	}
 
 	private boolean isUnboundidEnabled(String mode) {
-		return "unboundid".equals(mode) || ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader());
+		return "unboundid".equals(mode) || unboundIdPresent;
 	}
 
 	private String getPort(Element element) {
@@ -222,11 +232,11 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 		}
 
 		private int getPort() {
-			if (ClassUtils.isPresent(APACHEDS_CLASSNAME, getClass().getClassLoader())) {
+			if (apacheDsPresent) {
 				ApacheDSContainer apacheDSContainer = this.applicationContext.getBean(ApacheDSContainer.class);
 				return apacheDSContainer.getLocalPort();
 			}
-			if (ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader())) {
+			if (unboundIdPresent) {
 				UnboundIdContainer unboundIdContainer = this.applicationContext.getBean(UnboundIdContainer.class);
 				return unboundIdContainer.getPort();
 			}

+ 25 - 5
core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java

@@ -89,6 +89,26 @@ public final class SecurityJackson2Modules {
 
 	private static final String saml2Jackson2ModuleClass = "org.springframework.security.saml2.jackson2.Saml2Jackson2Module";
 
+	private static final boolean webServletPresent;
+
+	private static final boolean oauth2ClientPresent;
+
+	private static final boolean javaTimeJacksonPresent;
+
+	private static final boolean ldapJacksonPresent;
+
+	private static final boolean saml2JacksonPresent;
+
+	static {
+		ClassLoader classLoader = SecurityJackson2Modules.class.getClassLoader();
+		webServletPresent = ClassUtils.isPresent("jakarta.servlet.http.Cookie", classLoader);
+		oauth2ClientPresent = ClassUtils.isPresent("org.springframework.security.oauth2.client.OAuth2AuthorizedClient",
+				classLoader);
+		javaTimeJacksonPresent = ClassUtils.isPresent(javaTimeJackson2ModuleClass, classLoader);
+		ldapJacksonPresent = ClassUtils.isPresent(ldapJackson2ModuleClass, classLoader);
+		saml2JacksonPresent = ClassUtils.isPresent(saml2Jackson2ModuleClass, classLoader);
+	}
+
 	private SecurityJackson2Modules() {
 	}
 
@@ -125,19 +145,19 @@ public final class SecurityJackson2Modules {
 		for (String className : securityJackson2ModuleClasses) {
 			addToModulesList(loader, modules, className);
 		}
-		if (ClassUtils.isPresent("jakarta.servlet.http.Cookie", loader)) {
+		if (webServletPresent) {
 			addToModulesList(loader, modules, webServletJackson2ModuleClass);
 		}
-		if (ClassUtils.isPresent("org.springframework.security.oauth2.client.OAuth2AuthorizedClient", loader)) {
+		if (oauth2ClientPresent) {
 			addToModulesList(loader, modules, oauth2ClientJackson2ModuleClass);
 		}
-		if (ClassUtils.isPresent(javaTimeJackson2ModuleClass, loader)) {
+		if (javaTimeJacksonPresent) {
 			addToModulesList(loader, modules, javaTimeJackson2ModuleClass);
 		}
-		if (ClassUtils.isPresent(ldapJackson2ModuleClass, loader)) {
+		if (ldapJacksonPresent) {
 			addToModulesList(loader, modules, ldapJackson2ModuleClass);
 		}
-		if (ClassUtils.isPresent(saml2Jackson2ModuleClass, loader)) {
+		if (saml2JacksonPresent) {
 			addToModulesList(loader, modules, saml2Jackson2ModuleClass);
 		}
 		return modules;

+ 6 - 2
test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java

@@ -43,14 +43,18 @@ import org.springframework.util.StringUtils;
  */
 final class WithUserDetailsSecurityContextFactory implements WithSecurityContextFactory<WithUserDetails> {
 
-	private static final boolean reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Mono",
-			WithUserDetailsSecurityContextFactory.class.getClassLoader());
+	private static final boolean reactorPresent;
 
 	private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
 			.getContextHolderStrategy();
 
 	private BeanFactory beans;
 
+	static {
+		reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Mono",
+				WithUserDetailsSecurityContextFactory.class.getClassLoader());
+	}
+
 	@Autowired
 	WithUserDetailsSecurityContextFactory(BeanFactory beans) {
 		this.beans = beans;