diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java index 873936a492..9560ac2b24 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java +++ b/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> extends SecurityConfigurerAdapter { + 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> extends AbstractHttpConfigurer, 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> extends AbstractHt CorsConfigurationSource.class); return new CorsFilter(configurationSource); } - boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, context.getClassLoader()); if (mvcPresent) { return MvcCorsFilter.getMvcCorsFilter(context); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java index e72f9a5b4b..407436c165 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java +++ b/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." diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java index 7bc58cbc4a..04520c7e86 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java +++ b/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 securityWebFilterChains; private ObservationRegistry observationRegistry = ObservationRegistry.NOOP; + static { + isOAuth2Present = ClassUtils.isPresent(REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME, + WebFluxSecurityConfiguration.class.getClassLoader()); + } + @Autowired ApplicationContext context; diff --git a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java b/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java index 8ec6a81dfe..ead9135d95 100644 --- a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java +++ b/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 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)); } diff --git a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java index 8f7ccc1eab..94d8730062 100644 --- a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java +++ b/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; } diff --git a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java index cdf62504a5..57913e122d 100644 --- a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java +++ b/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, diff --git a/config/src/main/java/org/springframework/security/config/ldap/EmbeddedLdapServerContextSourceFactoryBean.java b/config/src/main/java/org/springframework/security/config/ldap/EmbeddedLdapServerContextSourceFactoryBean.java index 4a8c2d56d4..32a5806d85 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/EmbeddedLdapServerContextSourceFactoryBean.java +++ b/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); diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java index 3da012c375..bf78ee9c83 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java +++ b/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(); } diff --git a/core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java b/core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java index 15493a63b2..abccf9ac50 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java +++ b/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; diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java b/test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java index 094df9512b..b04e4f7e28 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java +++ b/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 { - 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;