From c108d2d01190ee527411f34b50ed6dec39ce2cc0 Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Sun, 8 Dec 2019 11:56:34 +0100 Subject: [PATCH] Detect DirContextAuthenticationStrategy bean This commit improves the LDAP auto-configuration to detect if a DirContextAuthenticationStrategy bean is defined and, if so, associates it with the auto-configured `LdapContextSource`. See gh-19328 --- .../ldap/LdapAutoConfiguration.java | 7 +- .../ldap/LdapAutoConfigurationTests.java | 73 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfiguration.java index afb14cf81cc..44ea3ec01a3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfiguration.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.ldap; import java.util.Collections; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -29,6 +30,7 @@ import org.springframework.core.env.Environment; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.LdapOperations; import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.DirContextAuthenticationStrategy; import org.springframework.ldap.core.support.LdapContextSource; /** @@ -45,7 +47,8 @@ public class LdapAutoConfiguration { @Bean @ConditionalOnMissingBean - public LdapContextSource ldapContextSource(LdapProperties properties, Environment environment) { + public LdapContextSource ldapContextSource(LdapProperties properties, Environment environment, + ObjectProvider authenticationStrategy) { LdapContextSource source = new LdapContextSource(); PropertyMapper propertyMapper = PropertyMapper.get().alwaysApplyingWhenNonNull(); propertyMapper.from(properties.getUsername()).to(source::setUserDn); @@ -55,6 +58,8 @@ public class LdapAutoConfiguration { propertyMapper.from(properties.determineUrls(environment)).to(source::setUrls); propertyMapper.from(properties.getBaseEnvironment()).to( (baseEnvironment) -> source.setBaseEnvironmentProperties(Collections.unmodifiableMap(baseEnvironment))); + + authenticationStrategy.ifUnique(source::setAuthenticationStrategy); return source; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfigurationTests.java index 796b3a99f52..be706c573d3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ldap/LdapAutoConfigurationTests.java @@ -16,6 +16,10 @@ package org.springframework.boot.autoconfigure.ldap; +import java.util.Hashtable; + +import javax.naming.directory.DirContext; + import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -24,9 +28,12 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.DirContextAuthenticationStrategy; import org.springframework.ldap.core.support.LdapContextSource; +import org.springframework.ldap.core.support.SimpleDirContextAuthenticationStrategy; import org.springframework.ldap.pool2.factory.PoolConfig; import org.springframework.ldap.pool2.factory.PooledContextSource; +import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -90,11 +97,14 @@ class LdapAutoConfigurationTests { @Test void contextSourceWithNoCustomization() { this.contextRunner.run((context) -> { + assertThat(context).doesNotHaveBean(DirContextAuthenticationStrategy.class); LdapContextSource contextSource = context.getBean(LdapContextSource.class); assertThat(contextSource.getUserDn()).isEqualTo(""); assertThat(contextSource.getPassword()).isEqualTo(""); assertThat(contextSource.isAnonymousReadOnly()).isFalse(); assertThat(contextSource.getBaseLdapPathAsString()).isEqualTo(""); + assertThat(ReflectionTestUtils.getField(contextSource, "authenticationStrategy")) + .isInstanceOf(SimpleDirContextAuthenticationStrategy.class); }); } @@ -113,6 +123,35 @@ class LdapAutoConfigurationTests { }); } + @Test + void contextSourceWithCustomUniqueDirContextAuthenticationStrategy() { + this.contextRunner.withUserConfiguration(CustomDirContextAuthenticationStrategy.class).run((context) -> { + assertThat(context).hasSingleBean(DirContextAuthenticationStrategy.class); + LdapContextSource contextSource = context.getBean(LdapContextSource.class); + assertThat(ReflectionTestUtils.getField(contextSource, "authenticationStrategy")) + .isEqualTo(context.getBean(DirContextAuthenticationStrategy.class)); + }); + } + + @Test + void contextSourceWithCustomNonUniqueDirContextAuthenticationStrategy() { + this.contextRunner.withUserConfiguration(CustomDirContextAuthenticationStrategy.class, + AnotherCustomDirContextAuthenticationStrategy.class).run((context) -> { + assertThat(context).hasBean("customDirContextAuthenticationStrategy") + .hasBean("anotherCustomDirContextAuthenticationStrategy"); + TestDirContextAuthenticationStrategy customDirContextAuthenticationStrategy = context.getBean( + "customDirContextAuthenticationStrategy", TestDirContextAuthenticationStrategy.class); + TestDirContextAuthenticationStrategy anotherCustomDirContextAuthenticationStrategy = context + .getBean("anotherCustomDirContextAuthenticationStrategy", + TestDirContextAuthenticationStrategy.class); + LdapContextSource contextSource = context.getBean(LdapContextSource.class); + assertThat(ReflectionTestUtils.getField(contextSource, "authenticationStrategy")) + .isNotEqualTo(customDirContextAuthenticationStrategy) + .isNotEqualTo(anotherCustomDirContextAuthenticationStrategy) + .isInstanceOf(SimpleDirContextAuthenticationStrategy.class); + }); + } + @Configuration(proxyBeanMethods = false) static class PooledContextSourceConfig { @@ -126,4 +165,38 @@ class LdapAutoConfigurationTests { } + @Configuration(proxyBeanMethods = false) + static class CustomDirContextAuthenticationStrategy { + + @Bean + DirContextAuthenticationStrategy customDirContextAuthenticationStrategy() { + return new TestDirContextAuthenticationStrategy(); + } + + } + + @Configuration(proxyBeanMethods = false) + static class AnotherCustomDirContextAuthenticationStrategy { + + @Bean + DirContextAuthenticationStrategy anotherCustomDirContextAuthenticationStrategy() { + return new TestDirContextAuthenticationStrategy(); + } + + } + + static class TestDirContextAuthenticationStrategy implements DirContextAuthenticationStrategy { + + @Override + public void setupEnvironment(Hashtable env, String userDn, String password) { + + } + + @Override + public DirContext processContextAfterCreation(DirContext ctx, String userDn, String password) { + return ctx; + } + + } + }