Accedere ad una directory LDAP con JNDI

Accedere ad una directory LDAP con JNDI

In questo poste vedremo come interrogare una directory LDAP tramite le API JNDI. Ricordiamo che LDAP è un protocollo standard per l'interrogazione e la modifica dei servizi di directory, nato come alternativa snella al DAP, in quanto richiede il più leggero e popolare protocollo TCP/IP invece della intera pila OSI. Inoltre LDAP semplifica certe operazioni di X.500 e omette certi aspetti intricati.

Hibernate: realizziamo un esempio pratico di utilizzo delle API di base
Linee guida per l’ottimizzazione del codice Java
Installare Liferay IDE

In questo poste vedremo come interrogare una directory LDAP tramite le API JNDI. Ricordiamo che LDAP  è un protocollo standard per l’interrogazione e la modifica dei servizi di directory, nato come alternativa snella al DAP, in quanto richiede il più leggero e popolare protocollo TCP/IP invece della intera pila OSI. Inoltre LDAP semplifica certe operazioni di X.500 e omette certi aspetti intricati.

Per poter eseguire il codice che andremo a sviluppare dobbiamo scaricare le librerie jar per il Service Provider (SPI) LDAP, le troviamo al sito:

https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=7110-jndi-1.2.1-oth-JPR@CDS-CDS_Developer

e scarichiamo il pacchetto .zip chiamato ldap-1_2_4 sotto la voce LDAP Service Provider, 1.2.4.

Ora creiamo un progetto Java in Eclipse  (File -> New -> Java Project), creiamo una cartella lib e vi copiamo le librerie che abbiamo appena scaricato:

  • jaas.jar;
  • ldap.jar;
  • ldapbp.jar;
  • ldapsec.jar;
  • providerutil.jar.

Per provare il nostro esempio dobbiamo avere a disposizione una directory LDAP da interrogare (a meno che non l’abbiamo già disponibile :)), possiamo dunque o crearne una nostra privata utilizzando una delle implementazioni Server disponibili in rete quali ad esempio OpenLDAP (disponibile per numerosi S.O. tra cui Windows e Linux), oppure possiamo andare ad interrogare delle directory pubbliche accessibili attraverso internet, in questo articolo seguiremo questa ultima strada. Di directory LDAP pubbliche non ce ne sono moltissime in rete, soprattutto delle più note università americane, tra queste abbiamo scelto quella della Cornell University (possiamo trovare maggiori informazioni a questo indirizzo http://www2.cit.cornell.edu/directory/) , dove possiamo interrogare la directory riguardante gli studenti, lo staff e gli insegnanti che riguardano tale università (dopo alcune ricerche ho notato che qualche ex-studente si è lamentato per la mancanza di privacy :P).

La prima cosa da fare è inizializzare il contesto JNDI , che nel caso di una directory prende il nome di InitialDirContext (sottoclasse di InitialContext), al cui costruttore forniamo le due properties INITIAL_CONTEXT_FACTORY e PROVIDER_URL. Successivamente definiamo un SearchControls su cui richiamiamo il metodo setSearchScope() passandogli la costante SUBTREE_SCOPE, così facendo la nostra ricerca di un dato oggetto sarà effettuata lungo tutto l’albero avente come radice il Named Object che passeremo al metodo di search.

L’interfaccia DirContext fornisce quattro metodi per la ricerca:

  • search(Name name, Attributes matchingAttrs)
  • search(Name name, Attributes matchingAttrs, String[] retAttrs)
  • search(Name name, String filter, SearchControls ctls)
  • search(Name name, String filterExpr, Object[] filterArgs, SearchControls ctls)

tutti questi metodo hanno poi una versione “overloaded” in cui può essere passato un parametro String invece che di tipo Name. Name appunto è il contesto iniziale in cui iniziare la ricerca (il target context che precedentemente abbiamo chiamato Named Object), mentre Attrbutes sono gli attributi che una data entry (quella che stiamo ricercando) deve avere, possiamo crearli in questo modo:

Attributes matchAttrs = new BasicAttributes(true); //case insensitive
matchAttrs.put(new BasicAttribute("givenname", "mario"));
matchAttrs.put(new BasicAttribute("sn"));

ricerchiamo un oggetto (entry) con givenname (nome) mario e surname (cognome) qualsiasi valore, * è il carattere jolly.

Altrimenti possiamo specificare gli attributi che dovrà avere il nostro oggetto utilizzando una semplice stringa che sarà il nostro filtro:

(&(givenname=mario)(sn=*))

dove l’operatore & concatena in and le due condizioni.

Il metodo search ritorna una NamingEnumeration (sottoclasse di Enumeration) di oggetti di tipo SearchResult (sottoclasse di Binding), dai quali possiamo estrarre il nome (getName()) e la loro lista di attributi (getAttributes()).  Su questa lista possiamo ricercarne uno in particolare (get(String name)) i cui valori possono essere multipli (getAll()).

Si riporta, di seguito, il codice di esempio completo:

package it.appuntisoftware;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.DirContext;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.NamingException;
import java.util.Hashtable;
public class LDAPAttributes {
public static void main(String[] args) {
// Specifichiamo il Service Provider da utilizzare
// e inseriamo l'URL del Server LDAP
Hashtable<String,String> env = new Hashtable<String,String>(2);
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://directory.cornell.edu/o=Cornell%20University,c=US");
try {
// Creiamo l'InitialContext di tipo Directory
DirContext ctx = new InitialDirContext(env);
SearchControls ctrl = new SearchControls();
ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Facciamo una ricerca a partire dal naming context "People"
NamingEnumeration<SearchResult> enumeration = ctx.search("ou=People", "(&(givenname=mario)(sn=*))", ctrl);
while (enumeration.hasMore()) {
SearchResult result = enumeration.next();//Stampiamo il nome dell'oggetto
System.out.print(result.getName()+": ");
Attributes attribs = result.getAttributes();
NamingEnumeration values = attribs.get("mail").getAll();
while (values.hasMore()) {
//Stampiamo a video gli attributi dell'oggetto
System.out.println(values.next().toString());
}
}
// Chiudiamo il context
ctx.close();
} catch (NamingException e) {
System.err.println("Problem getting attribute: " + e);
}
}
}

COMMENTS

WORDPRESS: 0