Pagina's

zaterdag 2 november 2013

Easy LDAP access with Unboundid

Lately I have been evaluating a couple of LDAP SDK's. The mean reason for this evaluation is the fact that the standard API provided with Java is not very coder-friendly. A lot of boilerplate code needs to be written even to do simple things.

The frameworks i've been looking at are: Unboundid, Ldaptive and Spring LDAP. In this article I will show an example of LDAP access using Unboundid LDAP SDK. Unboundid contains a sub-framework they call 'Unboundid LDAP SDK Persistence framework'. It contains annotation-based persistence support to/from LDAP. In this example I will add a user to LDAP and then read it again. The user can be annotated with Unboundid annotations and this makes it very easy to do a basic implementation.
First of all we create a new Maven project and add the following dependencies:

<dependencies>
    <dependency>
        <groupId>com.unboundid</groupId>
        <artifactId>unboundid-ldapsdk</artifactId>
        <version>2.3.4</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
</dependencies> 


Next, we define a User POJO which represents the User domain type. The POJO will be annotated by a couple of Unboundid annotations which indicate how the User is stored within LDAP.
package example;

import com.unboundid.ldap.sdk.persist.FilterUsage;
import com.unboundid.ldap.sdk.persist.LDAPField;
import com.unboundid.ldap.sdk.persist.LDAPObject;

@LDAPObject(structuralClass = "inetOrgPerson", defaultParentDN = "ou=people,dc=example,dc=com")
public class User {

    @LDAPField(attribute = "uid", inRDN = true, filterUsage = FilterUsage.ALWAYS_ALLOWED)
    private String id;
    @LDAPField(attribute = "cn")
    private String name;
    @LDAPField(attribute = "sn")
    private String surName;
    @LDAPField(attribute = "mail")
    private String emailAddress;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurName() {
        return surName;
    }

    public void setSurName(String surName) {
        this.surName = surName;
    }

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }
}

The @LDAPObject annotation indicates that the User object is stored in LDAP and is based on the structural LDAP class 'inetOrgPerson'. Furthermore, a parent DN is specified so Unboundid knows where to store/retrieve LDAP user records. The @LDAPField annotation specifies the way each User property is stored in LDAP. More info about these annotation can be found here: https://www.unboundid.com/products/ldap-sdk/docs/persist/index.php

Next we will define a Dao class which can be used to store/retrieve User's:

package example;


import com.unboundid.ldap.sdk.LDAPInterface;
import com.unboundid.ldap.sdk.persist.LDAPPersistException;
import com.unboundid.ldap.sdk.persist.LDAPPersister;

public class UserDao {

    private LDAPInterface ldapServer;
    private LDAPPersister<User> persister;

    public UserDao(LDAPInterface ldapServer) throws LDAPPersistException {
        this.ldapServer = ldapServer;
        this.persister = LDAPPersister.getInstance(User.class);
    }

    public User findUser(String id) throws LDAPPersistException {
        User userToFind = new User();
        userToFind.setId(id);
        User foundUser = persister.searchForObject(userToFind, ldapServer);
        return foundUser;
    }

    public void addUser(User user) throws LDAPPersistException {
        persister.add(user, ldapServer, null);
    }
}

This Dao class receives an ldap server obect through its constructor. This ldap server object provides a lot of low-level LDAP manipulation operations. It is used by a higher-level persister to persist annotated objects. The findUser and addUser methods show how easy this is. Just create a User instance and pass it to the persister.

To show how this works, we create a basic unit test. In this unit test, an in-memory directory server is created and an LDAP schema is loaded. After that, we add a user and then retrieve it again. It's as easy as this:

package example;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import org.junit.Assert;
import org.junit.Test;

public class AppTest {

    @Test
    public void testUnboundid() throws Exception {
        InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example, dc=com");
        config.addAdditionalBindCredentials("cn=Directory Manager", "password");

        InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
        ds.importFromLDIF(true, "src/test/resources/ldap.ldif");
        ds.startListening();
       
        UserDao userDao = new UserDao(ds);
       
        User newUser = new User();
        newUser.setId("jdoe");
        newUser.setName("John Doe");
        newUser.setSurName("doe");
        userDao.addUser(newUser);
               
        User foundUser = userDao.findUser("jdoe");
        Assert.assertEquals("John Doe", foundUser.getName());
    }

}
My conclusion is that Unboundid is a very useful framework for LDAP access. It takes away much of the low-level coding that would otherwise be necessary when using the basic JNDI classes.

Geen opmerkingen:

Een reactie posten