Monday, January 3, 2011

Apache Directory Service – LDAP - Tutorial

Apache Directory Service – LDAP - Tutorial
Apache Directory Service is an Open Source Java implementation. It implements LDAP (Light Weight Directory Access) protocol. It listens to client requests for directory service, and allows for storing application data (including runtime Java objects) in Apache Directory Service.

What is a Directory Service ?
A directory service is a service that exposes API to store and organize data. Generally, this data is not frequently updated like user data in a organization. User data consists of attributes like, name, designation, role, telephone number, email, etc. All this data can be stores in a directory service in an organized fashion. A directory service also provides query interface API to query this data by different applications.

What is LDAP ?
Acronym LDAP stands for Light Weight Directory Access Protocol. LDAP defines request and response messages for directory operations. Directory operations include CRUD operations on data that can be stores in the directory.
The LDAP request to store new data in the directory is called a bind message. A bind message saves user data in the LDAP directory.
LDAP stores data using DN. DN stands for Distinguished Name. DN is unique throughout the LDAP directory interface. LDAP allows for search of data using DN.

Installation of Apache Directory Server:
For my evaluations, I have used Apache Directory Studio. It can be found here - http://directory.apache.org/studio/downloads.html
Apache directory studio contains embedded LDAP server as well as LDAP browser. However, I have also used another tool called Jxplorer. It can be found here - http://jxplorer.org/

What are the objectClasses in ApacheDS?
The following screenshot shows the person class and it’s attributes in the Apache Directory Studio.

The screenshot shows person class and it’s attributes. There are certain attributes that are mandatory and certain attributes that are optional. The attributes cn and sn are mandatory attributes for person class.

What are the types of objectClasses ?
There are three types of object classes : abstract, structural, and auxiliary.  All objectclasses extend from a class called top. So, top is an abstract class. In above example, person class is demonstrated which is a structural class. Auxiliary class extend from structural class and are meant for specific user purpose. For example, organizationalPerson class.



What are attributeTypes?
The following screenshot shows the common name attribute in the Apache Directory Studio.

There are several fields that make up the cn attribute. One of them is EQUALITY. EQUALITY specifies a search value when a search criteria is given. The default value for this field is caseIgnoreMatch. Using this attribute during the search operation means that when a person is searched, it will be case insensitive.

How to add data to LDAP ?
I will show you how to add data to the LDAP. Go to the users branch and click New. Select values as shown in the screenshot below.

The following screenshot shows 2 users under the Users tab.

How to serialize Java Serializable class to LDAP server?
Given below is the sample source code for MessafingPreferences class which is serialized and stored as preferences for the user Alice Shaw.

Here’s the code:

package com.server;

import java.io.Serializable;

public class MessagingPreferences implements Serializable {

      static final long serialVersionUID = -1L;
     
     
      /**
       * @param args
       */
      public static void main(String[] args) {
            // TODO Auto-generated method stub

      }

}




package com.server;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class Preferences {
     
     
      public Preferences(){
        try {
            InputStream inputStream = new FileInputStream( "preferences.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            properties.setProperty("java.naming.security.credentials", "secret");

            DirContext ctx = new InitialDirContext(properties);

            MessagingPreferences preferences = new MessagingPreferences();

            String bindContext = "cn=preferences,cn=AliceShaw,ou=users";
            ctx.bind( bindContext, preferences);
        } catch (Exception e) {
            System.out.println("Operation failed: " + e);
        }
           
      }

      /**
       * @param args
       */
      public static void main(String[] args) {
            // TODO Auto-generated method stub
            Preferences pr = new Preferences();

      }

}




Here’s the properties file:

java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.url=ldap://localhost:10389/ou=system
java.naming.security.authentication=simple
java.naming.security.principal=uid=admin,ou=system



The above 3 files are required on the Java client side to interface to the Apache Directory Server.

After running the source code, the user Alice Shaw has preferences branch which stores the MessagingPreferences class.


How to search for a particular user inside LDAP directory server?
The following code example demonstrates how to search for a particular user in the Apache Directory Server.


package com.server;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;

import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchResult;

public class SearchUser {
     

          public SearchUser() {
              try
              {
                  InputStream inputStream = new FileInputStream( "preferences.properties");
                  Properties properties = new Properties();
                  properties.load(inputStream);
                  properties.setProperty("java.naming.security.credentials", "secret");

                  DirContext ctx = new InitialDirContext(properties);
         
                  String searchContext = "ou=users";

                  Attribute cn = new BasicAttribute("cn");
                  Attribute objclass = new BasicAttribute("objectClass");

                  cn.add("AliceShaw");
                  objclass.add("person");

                  //Instantiate an Attributes object and put search attributes in it
                  Attributes attrs = new BasicAttributes(true);
                  attrs.put(cn);
                  attrs.put(objclass);

                  NamingEnumeration ne = ctx.search(searchContext, attrs);
                 
                  if (ne != null)
                  {

                      while (ne.hasMore()) {

                          SearchResult sr = (SearchResult) ne.next();

                          String entryRDN = sr.getName();

                          Attributes srAttrs = sr.getAttributes();

                          if (srAttrs != null) {
                               for (Enumeration e = attrs.getAll() ; e.hasMoreElements() ;)
                               {
                                    Attribute attr = (Attribute) e.nextElement();

                                    String attrID = attr.getID(); 
                                    System.out.println("Attribute Name: "+attrID);
                                    System.out.println("Attribute Value(s):");

                                    NamingEnumeration e1 = attr.getAll();
                                      while (e1.hasMore())
                                         System.out.println("\t\t"+e1.nextElement());
                               }//for()
                          }//if (srAttrs)
                      }
                  }//if (ne != null)
                      
              } catch (Exception e) {
                  System.out.println("Operation failed: " + e);
              }
          }
     
     

      /**
       * @param args
       */
      public static void main(String[] args) {
            // TODO Auto-generated method stub
            SearchUser su = new SearchUser();
      }

}



The above code sample gives following output:

Attribute Name: objectClass
Attribute Value(s):
            person
Attribute Name: cn
Attribute Value(s):
            AliceShaw




The above code shows that using LDAP API, and the Apache Directory Service, previously stored data can be searched and retrieved.

Conclusion
This kind of mechanism can be easily used as a User management and authentication mechanism for enterprise applications. Users can be stored in the Apache Directory Server and enterprise applications can connect to the LDAP server and authenticate and authorize the server.

1 comment: