LDAP and JNDI


12 Jul 2020  Sergio Martin Rubio  4 mins read.

LDAP (Lightweight Directory Access Protocol) is a directory service in which you can store data. The information stored in LDAP is structured in a tree hierarchy and each directory object is called an entry. An entry contains the following components:

  • DN (Distinguished Name): identifies an entry and consists of single entries names separated by a comma and ordered right-to-left.
  • Object classes: An object class is the schema of an entry that organizes and determines the content of the entry.
  • Attributes: contain the actual data.

Entry’s attributes are created like this:

<attributeName>=<attributeValue>

e.g.

cn=Sergio

LDAP Server

  1. Download Apache Directory Studio

    Apache Directory Studio association 2.0.0-M15 requires Java 8. Make sure you do not have any other Java version under /Library/Java/JavaVirtualMachines on MacOS.

  2. Go to LDAP Servers tab in the bottom left corner and click on New LDAP Server.
  3. Select latest version and click on Finish.
  4. Create a connection by right clicking on the new LDAP server.
  5. Start up the server.
  6. Now we can go to the LDAP Browser tab.
  7. Import some data
    ## DEFINE DIT ROOT/BASE/SUFFIX ####
    ## uses RFC 2377 format
    ## replace example and com as necessary below
    ## or for experimentation leave as is
    ## dcObject is an AUXILLIARY objectclass and MUST
    ## have a STRUCTURAL objectclass (organization in this case)
    # this is an ENTRY sequence and is preceded by a BLANK line
    dn: dc=example,dc=com
    dc: example
    description: My wonderful company as much text as you want to place
    in this line up to 32K continuation data for the line above must
    have <CR> or <CR><LF> i.e. ENTER works
    on both Windows and *nix system - new line MUST begin with ONE SPACE
    objectClass: dcObject
    objectClass: organization
    o: Example, Inc.
    ## FIRST Level hierarchy - people
    ## uses mixed upper and lower case for objectclass
    # this is an ENTRY sequence and is preceded by a BLANK line
    dn: ou=people, dc=example,dc=com
    ou: people
    description: All people in organisation
    objectclass: organizationalunit
    ## SECOND Level hierarchy
    ## ADD a single entry under FIRST (people) level
    # this is an ENTRY sequence and is preceded by a BLANK line
    # the ou: Human Resources is the department name
    dn: cn=Robert Smith,ou=people,dc=example,dc=com
    objectclass: inetOrgPerson
    cn: Robert Smith
    cn: Robert J Smith
    cn: bob smith
    sn: smith
    uid: rjsmith
    userpassword: rJsmitH
    carlicense: HISCAR 123
    homephone: 555-111-2222
    mail: r.smith@example.com
    mail: rsmith@example.com
    mail: bob.smith@example.com
    description: swell guy
    ou: Human Resources

JNDI Integration

LDAP is one of the service providers that comes with JDK out-of-the-box, so you can use the JNDI API to perform operations on LDAP server.

Getting Started

You only need the javaee-api dependency to starting using LDAP with JNDI.

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>8.0.1</version>
    <scope>provided</scope>
</dependency>

LDAP Context

The LDAP context can be created as follows:

Properties properties = new Properties();
properties.setProperty(INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
properties.setProperty(PROVIDER_URL, "ldap://localhost:10389/dc=example,dc=com");
DirContext context = new InitialDirContext(properties);

The port of LDAP server can be found in Apache Directory Studio.

Organizational Units

You can see all the organizational units with:

Properties properties = new Properties();
properties.setProperty(INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
properties.setProperty(PROVIDER_URL, "ldap://localhost:10389/dc=example,dc=com");
DirContext context = new InitialDirContext(properties);

NamingEnumeration<Binding> bindings = context.listBindings("");
while (bindings.hasMoreElements()) {
    System.out.println(bindings.next().getName());
}

Attributes

To access the entries in a organization unit:

Properties properties = new Properties();
properties.setProperty(INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
properties.setProperty(PROVIDER_URL, "ldap://localhost:10389/dc=example,dc=com");
DirContext context = new InitialDirContext(properties);

DirContext peopleContext = (DirContext) context.lookup("ou=people");

NamingEnumeration<Binding> people = peopleContext.listBindings("");
while (people.hasMoreElements()) {
    String bindingName = people.next().getName();
    Attributes personAttributes = peopleContext.getAttributes(bindingName);
    Attribute description = personAttributes.get("description");
    Attribute mailsAttribute = personAttributes.get("mail");
    Attribute personName = personAttributes.get("cn");

    NamingEnumeration<?> personNames = personName.getAll();
    System.out.println("Person names:");
    while (personNames.hasMoreElements()) {
        System.out.println(personNames.next());
    }
    System.out.println();

    System.out.printf("Description: %s\n\n", description.get());

    NamingEnumeration<?> mails = mailsAttribute.getAll();
    System.out.println("Mails:");
    while (mails.hasMoreElements()) {
        System.out.println(mails.next());
    }
}

This will print out the following given the example ldif file:

Person names:
Robert Smith
Robert J Smith
bob  smith

Description: swell guy

Mails:
r.smith@example.com
rsmith@example.com
bob.smith@example.com

Examples

Image by Ro Ma from Pixabay