Web technologies/2014-2015/Laboratory 11

LDAP

edit

The Lightweight Directory Access Protocol (LDAP) is an application protocol for quering directory services over TCP/IP.

A directory service is a software that stores/organises/handles access to the information stored inside a directory.

An LDAP session is started by connecting to an LDAP server (Directory System Agent - DSA) on the default TCP port 389.

LDAP is based on a simple information tree called the directory information tree (DIT) whose leafs are entry data.

An entry data has a Distinguished Name (DN) - a unique identifier - and any number of attribute/value pairs. A DN could look as follows: dn: uid=john,ou=info,o=university.com, where uid, ou and o represent mnemonics.

Example of mnemonics include:

  • o - Organization
  • ou - Organizational unit
  • cn - Common name
  • sn - Surname
  • givenname - First name
  • uid - Userid
  • dn - Distinguished name
  • mail - Email address

NOTE: Some of them are also used when generating keys for signing jars.

IMPORTANT: A DN is not an attribute nor part of the entry

IMPORTANT: The path of a DN is read from right to left: thus in our example uid represents the Relative Distinguished Name (RDN) while ou and o represent the parent entry. (the hierarchy could look like: university.com/info/john)

IMPORTANT: The entry attribute/value pairs follow the DNs definition

An LDAP URL for direct access looks as follows: ldap://host:port/DN?attributes?scope?filter?extensions where:

  • host - represents the host name
  • port - represents the port value
  • DN - represents the DN intended for query
  • attribute - represents the needed attributes. They should be comma separated
  • scope - represents the search scope. Can be: "base" (the default), "one" or "sub"
  • filter - represents a search filter
  • extensions - represent additions URL extensions

OpenLDAP is a free open-source implementation of the LDAP protocol. Its last version is as of Nov. 27th 2009: 2.4.20.

Links:

JNDI

edit

The Java Naming and Directory Interface (JNDI) is a Java API for discovering and handling data inside a service directory. It can be regarded as an analogue for JDBC.

The current version is as of 2006 JNDI 1.2.


The steps required for accessing and quering an LDAP directory through JNDI are:

  • Connect to the server
  • Authenticate (bind) to the server
  • Add/modify/delete/search entries

Objects can be stored in the database in the following ways:

  • as Java objects themselves
  • as a reference to the object
  • as attributes

The following example shows these steps and stores data as a Java object :


import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.NameAlreadyBoundException;
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.ModificationItem;
import javax.naming.directory.SearchResult;
import java.util.Hashtable;

[...]

Hashtable<String, String> env = new Hashtable<String, String>();

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
env.put(Context.SECURITY_AUTHENTICATION,"simple");
// Specify the username.
env.put(Context.SECURITY_PRINCIPAL,"cn=Directory Manager"); 
// Specify the password.
env.put(Context.SECURITY_CREDENTIALS,"yourPass");

try {
	DirContext ctx = new InitialDirContext(env);
	// Create some random number to add to the directory.
	Integer i = new Integer( 28420 );
	ctx.bind( "cn=myRandomInt", i );
        // Retrieve the integer based on its CN                
	i = (Integer) ctx.lookup( "cn=myRandomInt" );
	System.out.println( "Retrieved i from directory with value: " + i );

	// Replace/add/remove attributes by using 
	ModificationItem[] mods = new ModificationItem[3];
	Attribute mod0 = new BasicAttribute("attr1","value1");
	Attribute mod1 = new BasicAttribute("attr1", "value2");
	mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,mod0);
	mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,mod1);
	mods[2] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,mod1);
	
	ctx.modifyAttributes("cn=myRandomInt", mods);

	// Search for entries based on attribute values
	Attributes matchAttrs = new BasicAttributes(true);
	matchAttrs.put(mod1);
	NamingEnumeration<?> answer = ctx.search("cn=myRandomInt",matchAttrs);

	while (answer.hasMore()) {
		SearchResult sr = (SearchResult)answer.next();
		System.out.println("SEARCH RESULT:" + sr.getName());
		for (NamingEnumeration<?> en = sr.getAttributes().getAll(); en.hasMore();) {
			Attribute attrib = (Attribute)en.next();
			System.out.println("ATTRIBUTE :" + attrib.getID());
			for (NamingEnumeration<?> e = attrib.getAll();e.hasMore();)
				System.out.println("\t\t        = " + e.next());
		}
	}
	ctx.close();
} catch (Exception e) {
	e.printStackTrace();
}


Links:

Exercises

edit
  • Install OpenLDAP
  • The same exercise as in Laborator 9 but store the information inside an LDAP directory service not in a database.