Move classpath checks to class member variable

Closes gh-11437
This commit is contained in:
Marcus Da Coregio 2023-01-13 09:50:01 -03:00
parent c15f45d9ee
commit 52ed165476
13 changed files with 134 additions and 35 deletions

View File

@ -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);

View File

@ -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."

View File

@ -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[] {

View File

@ -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);
}

View File

@ -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."

View File

@ -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;

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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();
}

View File

@ -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;

View File

@ -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;