简体   繁体   中英

Best practice for configuring Spring LdapTemplate via annotations instead of XML?

For a Spring Boot application, I successfully configured a Spring LdapTemplate using annotations , including the LdapContextSource dependency with @Value s from application.properties. (Woot! I couldn't find an example, so maybe this will help others.)

The snippets (below) setup the context source, inject it into an LdapTemplate , and autowire that into my DirectoryService.

Is there a better/cleaner way to setup the ContextSource in a Spring Boot app?

application.properties (on the classpath):

ldap.url=ldap://server.domain.com:389
ldap.base:OU=Employees,OU=Users,DC=domain,DC=com
ldap.username:CN=myuserid,OU=employees,OU=Users,DC=domain,DC=com
ldap.password:secretthingy

MyLdapContextSource.java :

@Component
public class MyLdapContextSource extends LdapContextSource implements ContextSource {

    @Value("${ldap.url}")
    @Override
    public void setUrl(String url) { super.setUrl(url);  }

    @Value("${ldap.base}")
    @Override
    public void setBase(String base) {super.setBase(base); }

    @Value("${ldap.username}")
    @Override
    public void setUserDn(String userDn) {super.setUserDn(userDn); }

    @Value("${ldap.password}")
    @Override
    public void setPassword(String password) { super.setPassword(password); }
}

MyLdapTemplate.java:

@Component
public class MyLdapTemplate extends LdapTemplate {

    @Autowired
    public MyLdapTemplate(ContextSource contextSource) { super(contextSource); }
}

DirectoryService.java:

@Service
public class DirectoryService {

    private final LdapTemplate ldapTemplate;

    @Value("${ldap.base}")
    private String BASE_DN;

    @Autowired
    public DirectoryService(LdapTemplate ldapTemplate) { this.ldapTemplate = ldapTemplate; }

    public Person lookupPerson(String username) {
        return (Person) ldapTemplate.lookup("cn=" + username, new PersonAttributesMapper());
    }

    public List<Person> searchDirectory(String searchterm) {
        SearchControls searchControls = new SearchControls();
        searchControls.setCountLimit(25);
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        List<Person> people = (List<Person>) ldapTemplate.search(
                BASE_DN, "cn=" + searchterm, searchControls, new PersonAttributesMapper());
        return people;
    }
}

Why all the subclasses? Just use configuration to configure the beans. Either XML or Java Config.

@Configuration
public class LdapConfiguration {

    @Autowired
    Environment env;

    @Bean
    public LdapContextSource contextSource () {
        LdapContextSource contextSource= new LdapContextSource();
        contextSource.setUrl(env.getRequiredProperty("ldap.url"));
        contextSource.setBase(env.getRequiredProperty("ldap.base"));
        contextSource.setUserDn(env.getRequiredProperty("ldap.user"));
        contextSource.setPassword(env.getRequiredProperty("ldap.password"));
        return contextSource;
    }

    @Bean
    public LdapTemplate ldapTemplate() {
        return new LdapTemplate(contextSource());        
    }

}

Your DirectoryService can remain the same as it will have the LdapTemplate autowired.

A general rule of thumb is that you don't want to extend your infrastructure beans (like DataSource or LdapTemplate ) but configure them explicitly. This as opposed to your application beans (services, repositories etc.).

Explicit wiring up of your LDAP isn't necessary at all for straight forward cases. This is the sort of thing Spring Boot aims to eliminate by being opinionated in the first place.

Ensure you have the spring-boot-starter-data-ldap or the spring-ldap-core dependency included, eg for Maven in your pom:xml :

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>

Configure your LDAP in application.properties with the following keys:

# Note the spring prefix for each and use just the CN for username
spring.ldap.url=ldap://server.domain.com:389
spring.ldap.base=OU=Employees,OU=Users,DC=domain,DC=com
spring.ldap.username=myuserid
spring.ldap.password=secretthingy

Then simply rely on Spring to autowire, eg using field injection 1 :

@Autowired
private final LdapTemplate ldapTemplate;

Reference: Spring Boot Reference Guide: LDAP


1 Field injection is generally not recommended but it's used here for concision.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM