Tutoriel sur le projet LDAP Apache Directory (serveur, plugin Eclipse et API Java)

Apache Directory

Présentation du projet Apache Directory et de ses sous-projets Apache Directory Server (serveur LDAP), Apache Directory Studio (plugin Eclipse de consultation et d'édition de LDAP) et Apache Directory LDAP API (API Java d'accès LDAP).

Une discussion a été ouverte pour les commentaires sur la publication de cet article : [Commentez Donner une note à l'article (5)]

Article lu   fois.

L'auteur

HomeViadeoLinkedIn

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. INTRODUCTION

I-A. Objectif de l'article

L'objectif de cet article est de présenter le projet Apache Directory. Ce projet a été initialisé par Alex Karasulu en 2002.

Apache Directory est une solution LDAP très complète. Il comprend entre autres sous-projets un serveur LDAP Apache Directory Server, un plugin Eclipse Apache Directory Studio, une API Java Apache Directory LDAP API.

I-B. Attributs LDAP utilisés dans l'article

Sans prétendre à présenter la structure d'un LDAP, voici une brève explication des attributs utilisés dans cet article :

  • dn : Distinguished Name, c'est l'identifiant unique de l'entrée (c'est la combinaison de plusieurs des autres attributs, généralement le rdn de l'entrée avec le dn de l'entrée de niveau supérieur) ;
  • rdn : Relative Distinguished Name, c'est l'identifiant unique de l'entrée (c'est une combinaison d'attributs qui rend cette entrée unique dans son niveau) ;
  • objectclass : permet de définir le type de l'entrée (inetOrgPerson par exemple). Selon le type choisi, l'entrée pourra avoir des attributs différents (une organization n'a pas de uid) et une entrée peut cumuler des types ;
  • dc : Domain Component, c'est un morceau de nom de domaine (par exemple, com ou developpez) ;
  • o : Organization, c'est le nom de l'organisation pour une entrée de type organization, cela peut être le nom d'une entreprise/association ;
  • ou : Organization Unit, c'est une partie d'une entrée de type organization, cela peut être le service d'une entreprise ;
  • cn : Common Name, c'est le nom complet (par exemple : Régis POUILLER) ;
  • sn : Surname, c'est le surnom (par exemple : regis1512) ;
  • uid : User ID, c'est son identifiant (cela correspond souvent à son rdn).

Il y a d'autres attributs qui se passent de commentaires (mail, téléphone, description, userPassword).

II. APACHE DIRECTORY SERVER

II-A. Présentation

Apache Directory Server est un serveur LDAP écrit en Java. Il est écrit en Java (et donc multiplateforme).

Par ailleurs, il est certifié LDAPv3, extensible et supporte les déclencheurs (triggers) et les procédures stockées. Il est également serveur Kerberos.

Dans cet article, nous verrons son installation ainsi que sa possibilité à être embarquable.

II-B. Installation

Il faut télécharger le fichier d'installation (dans l'article la version 2.0.0-M15 pour Windows) à l'adresse : http://directory.apache.org/apacheds/download/download-windows.html.

La version 2.0.0-M15 comporte un bogue assez agaçant qui bloque le démarrage du service. Le bogue est identifiable en changeant le niveau de logsConfiguration du niveau de logs.

Cela sera corrigé dans la prochaine version (milestone M16) de Apache Directory Server.

Lancer l'exécutable « apacheds-2.0.0-M15.exe ».

Cliquer sur le bouton « Next > ».

Image non disponible

Cliquer sur le bouton « I Agree ».

Image non disponible

Choisir un dossier d'installation et cliquer sur le bouton « Next > ».

Image non disponible

Choisir un dossier pour stocker les données et cliquer sur le bouton « Next > ».

Image non disponible

Indiquer le dossier d'installation de Java et cliquer sur le bouton « Install ».

Image non disponible

Attendre la fin de l'installation.

Image non disponible

Cliquer sur le bouton « Next > ».

Image non disponible

Cliquer sur le bouton « Finish ».

Image non disponible

Cliquer sur le bouton « Oui ».

Image non disponible

Le service est démarré (visible dans les services Windows et dans le fichier log ci-dessous).

Image non disponible
C:\Program Files\ApacheDS\instances\default\log\wrapper.log
Sélectionnez
STATUS | wrapper  | 2013/11/11 18:47:39 | ApacheDS - default installed.
STATUS | wrapper  | 2013/11/11 18:52:47 | Starting the ApacheDS - default service...
STATUS | wrapper  | 2013/11/11 18:52:47 | --> Wrapper Started as Service
STATUS | wrapper  | 2013/11/11 18:52:47 | Launching a JVM...
INFO   | jvm 1    | 2013/11/11 18:52:48 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO   | jvm 1    | 2013/11/11 18:52:48 |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
INFO   | jvm 1    | 2013/11/11 18:52:48 | 
INFO   | wrapper  | 2013/11/11 18:52:52 | Waiting to start...
INFO   | wrapper  | 2013/11/11 18:52:57 | Waiting to start...
INFO   | jvm 1    | 2013/11/11 18:53:01 |            _                     _          ____  ____   
INFO   | jvm 1    | 2013/11/11 18:53:01 |           / \   _ __    ___  ___| |__   ___|  _ \/ ___|  
INFO   | jvm 1    | 2013/11/11 18:53:01 |          / _ \ | '_ \ / _` |/ __| '_ \ / _ \ | | \___ \  
INFO   | jvm 1    | 2013/11/11 18:53:01 |         / ___ \| |_) | (_| | (__| | | |  __/ |_| |___) | 
INFO   | jvm 1    | 2013/11/11 18:53:01 |        /_/   \_\ .__/ \__,_|\___|_| |_|\___|____/|____/  
INFO   | jvm 1    | 2013/11/11 18:53:01 |                |_|                                       
INFO   | jvm 1    | 2013/11/11 18:53:01 | 
INFO   | wrapper  | 2013/11/11 18:53:02 | Waiting to start...
STATUS | wrapper  | 2013/11/11 18:53:04 | ApacheDS - default started.

II-C. Configuration du niveau de logs

Par défaut les logs de Apache Directory Server sont au niveau « FATAL ». Il est souhaitable de descendre le niveau à « ERROR ». Pour avoir une idée des différents niveaux de logs possibles, il est possible de consulter l'article « Introduction à Log4J » de Sébastien Le Ray et notamment le chapitre « II.B. Niveaux de journalisation ».

Ouvrir le fichier « dossierApacheDS/instances/default/conf/log4j.properties » et modifier la ligne ci-dessous.

 
Sélectionnez
log4j.logger.org.apache.directory.server=ERROR

Après modification, redémarrer le service Windows de Apache Directory Server (ApacheDS).

Image non disponible

Cette modification permet d'identifier le problème avec la 2.0.0-M15 évoqué dans le II-BInstallation.

II-D. Serveur embarqué

Cette partie s'inspire des éléments de embedded-apacheds de rpwaltz sur Bitbucket qui est un fork de embedded-apacheds de resah sur Bitbucket.

Nous allons voir un exemple d'exécution d'Apache Directory Server en serveur embarqué (cela peut être utile dans le cadre de tests automatisés nécessitant un serveur LDAP, par exemple les tests d'une API de sécurité ou pour une application utilisant un LDAP mais dont on souhaite avoir la possibilité d'une installation « light » sans serveur à part). Durant cette exécution, nous allons charger une entrée de classe « inetOrgPerson » et le domaine la contenant que nous lirons avec une partie cliente.

Voici la dépendance Maven nécessaire à l'exécution.

Dépendance Maven
Sélectionnez
<dependency>
    <groupId>org.apache.directory.server</groupId>
    <artifactId>apacheds-all</artifactId>
    <version>2.0.0-M15</version>
</dependency>

Voici le fichier LDIF contenant l'entrée à charger.

rpouiller.ldif
Sélectionnez
version: 1

dn: o=TEST
objectclass: domain
objectclass: top
objectclass: extensibleObject
dc: TEST
o: TEST

dn: uid=rpouiller,o=TEST
objectClass: top
objectClass: inetOrgPerson
objectClass: person
objectClass: organizationalPerson
cn: Régis Pouiller
sn: regis1512
uid: rpouiller

Voici le code source de l'exemple.

EmbeddedServerMain.java
Sélectionnez
package com.developpez.rpouiller;

import java.io.File;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.partition.Partition;
import org.apache.directory.server.core.factory.DefaultDirectoryServiceFactory;
import org.apache.directory.server.core.factory.DirectoryServiceFactory;
import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;

public class EmbeddedServerMain {

    public static void main(String[] args) throws Exception {

        final DirectoryServiceFactory lFactory = new DefaultDirectoryServiceFactory();
        lFactory.init("Test");
        System.out.println("Factory initialisée");

        final DirectoryService lService = lFactory.getDirectoryService();
        lService.getChangeLog().setEnabled(false);
        lService.setShutdownHookEnabled(true);

        final Partition lPartition = new AvlPartition(lService.getSchemaManager());
        lPartition.setId("Test");
        lPartition.setSuffixDn(new Dn(lService.getSchemaManager(), "o=TEST"));
        lPartition.initialize();
        lService.addPartition(lPartition);
        System.out.println("Partition ajoutée au service");

        final LdapServer lServer = new LdapServer();
        lServer.setTransports(new TcpTransport("localhost", 11389));
        lServer.setDirectoryService(lService);
        System.out.println("Serveur initialisé");

        lService.startup();
        lServer.start();
        System.out.println("Serveur et service démarrés");

        new LdifFileLoader(lService.getAdminSession(), new File("rpouiller.ldif"), null).execute();
        System.out.println("Données LDIF chargées");

        System.out.println();
        System.out.println("Lecture de données - Début");

        final Hashtable<String, String> lEnvironment = new Hashtable<String, String>();
        lEnvironment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        lEnvironment.put(Context.PROVIDER_URL, "ldap://localhost:11389/");

        final LdapContext lLdapContext = new InitialLdapContext(lEnvironment, new Control[0]);
        final SearchControls lSearchControls = new SearchControls();
        lSearchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        final NamingEnumeration<SearchResult> lResultats = lLdapContext.search("", "(uid=rpouiller)", lSearchControls);
        System.out.println("\t Résultat trouvé : ");
        while (lResultats.hasMore()) {
            System.out.println("\t\t " + lResultats.next().getName());
        }

        System.out.println("Lecture de données - Fin");
        System.out.println();

        lServer.stop();
        lService.shutdown();
        System.out.println("Serveur et service arrêtés");
    }
}

Voici le résultat de l'exécution.

Trace de l'exécution
Sélectionnez
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Factory initialisée
Partition ajoutée au service
Serveur initialisé
Serveur et service démarrés
Données LDIF chargées

Lecture de données - Début
     Résultat trouvé : 
         uid=rpouiller,o=TEST
Lecture de données - Fin

Serveur et service arrêtés

La DirectoryServiceFactory permet d'instancier le DirectoryServiceDirectoryService. Le gère le LDAP : il contient la Partition et les entrées du LDAP. Le LdapServer traite les requêtes TCP et transmet tout cela au DirectoryService.

III. APACHE DIRECTORY STUDIO

III-A. Présentation

Apache Directory Studio est un plugin Eclipse contenant tous les outils nécessaires pour travailler avec un LDAP : navigateur LDAP, éditeur de fichier LDIF, serveur embarqué, éditeur de configuration…

III-B. Installation

Dans Eclipse (version utilisée ici 4.3.1 Kepler), sélectionner « Install New Software... » dans le menu « Help ».

Image non disponible

Cliquer sur le bouton « Add... ».

Image non disponible

Renseigner « Name » et « Location » (avec http://directory.apache.org/studio/update/2.x) et cliquer sur le bouton « OK ».

Image non disponible

Cocher « Apache Directory Studio ApacheDS 2.0 Configuration », « Apache Directory Studio ApacheDS Configuration », « Apache Directory Studio LDAP Browser », « Apache Directory Studio LDAP Servers », « Apache Directory Studio LDIF Editor » et « Apache Directory Studio Schema Editor » puis cliquer sur le bouton « Next > ».

Image non disponible

Cliquer sur le bouton « Next > ».

Image non disponible

Sélectionner « I accept the terms of the license agreement » puis cliquer sur le bouton « Finish ».

Image non disponible

Attendre la fin de l'installation.

Image non disponible

Cliquer sur le bouton « OK ».

Image non disponible

Cliquer sur le bouton « Yes ».

Image non disponible

III-C. Ouverture de la perspective « LDAP »

Sélectionner « Open perspective » / « Other... » dans le menu « Window ».

Image non disponible

Sélectionner « LDAP » et cliquer sur le bouton « OK ».

Image non disponible

La perspective comporte les vues suivantes : « LDAP Servers », « Connexions », « Navigateur LDAP », « Logs de modifications » et « Logs de recherches ».

Image non disponible

III-D. Vue « LDAP Servers »

La vue « LDAP Servers » permet de créer des serveurs LDAP dans Eclipse sans avoir besoin d'installer un LDAP sur le poste du développeur.

III-D-1. Création d'un serveur dans Eclipse

Pour créer un nouveau serveur, cliquer sur l'icône Image non disponible.

Image non disponible

Choisir « ApacheDS 2.0.0 » et cliquer sur le bouton « Finish ».

Image non disponible

III-D-2. Modification du port d'un serveur

Pour ouvrir la configuration, faire un clic droit sur le serveur juste créé et choisir « Ouvrir la configuration ».

Image non disponible

Modifier les ports du serveur afin de ne pas être en conflit avec le serveur installé dans le II-BInstallation. Puis sauver le fichier « config.ldif ».

Image non disponible

III-D-3. Démarrage du serveur et création d'une connexion vers le serveur dans Eclipse

Pour démarrer le serveur, cliquer sur l'icône Image non disponible.

Image non disponible

Pour créer une connexion vers ce serveur, faire un clic droit sur le serveur et choisir « Créer une connexion ».

Image non disponible

Cliquer sur le bouton « OK ».

Image non disponible

III-E. Vue « Connexions »

La vue « Connexions » permet de créer et d'utiliser des connexions vers des serveurs LDAP.

III-E-1. Déconnexion du serveur

La connexion vers le serveur créée dans le chapitre précédent a été ajoutée dans la vue « Connexions ». Pour fermer la connexion, cliquer sur l'icône Image non disponible

Image non disponible

III-E-2. Création d'une connexion vers un serveur externe

Pour créer une nouvelle connexion (vers le serveur installé dans le II-BInstallation), cliquer sur l'icône Image non disponible

Image non disponible

Saisir les informations sur la connexion : nom de la connexion (ici : « DS sur localhost »), nom de l'hôte (ici : « localhost ») et port (ici : « 10389 »). Puis cliquer sur le bouton « Next > ».

Image non disponible

Saisir le nom d'utilisateur (par défaut : « uid=admin,ou=system »). Décocher « Sauvegarder le mot de passe » (de toutes manières, nous allons le changer). Puis cliquer sur le bouton « Finish ».

Image non disponible

Saisir le mot de passe de l'utilisateur (par défaut : « secret »). Puis cliquer sur le bouton « OK ».

Image non disponible

La connexion a été créée et ouverte.

Image non disponible

III-E-3. Création d'une nouvelle partition

Pour ouvrir la configuration, faire un clic droit sur la connexion et choisir « Open configuration ».

Image non disponible

Pour aller vers la configuration des partitions, cliquer sur « Configuration avancée des partitions… » ou sur l'onglet « Partitions ».

Image non disponible

Cliquer sur le bouton « Ajouter ».

Image non disponible

Saisir les informations ID (ici : « developpez ») et suffix (ici : « dc=developpez,dc=com »). Puis sauver le fichier de configuration.

Image non disponible

À partir de ce que l'on a vu précédemment, fermer la connexion dans Eclipse, redémarrer le service Windows d'ApacheDS, ouvrir la connexion dans Eclipse.

La nouvelle partition est maintenant visible dans le « Navigateur LDAP ».

Image non disponible

III-F. Vue « Navigateur LDAP »

La vue « Navigateur LDAP » permet de consulter et d'éditer un LDAP (par exemple ici, modifier la valeur d'un attribut et créer une entrée).

III-F-1. Modification de la valeur d'un attribut

Nous allons modifier la valeur de l'attribut « userPassword » (le mot de passe) de l'utilisateur admin du LDAP.

Dans le « Navigateur LDAP », sélectionner l'entrée « uid=admin ».

Image non disponible

Noter que le mot de passe est visible en clair dans la vue « Outline ».

Image non disponible

Pour modifier la valeur, double-cliquer sur la valeur de l'attribut.

Image non disponible

Pour certaines valeurs (comme pour le mot de passe) un éditeur particulier apparaît. Dans l'onglet « Nouveau mot de passe », saisir le nouveau mot de passe (ici : « nouveausecret »), sélectionner la méthode de hachage (ici : « SHA »). Puis cliquer sur le bouton « OK ».

Image non disponible

Noter que le mot de passe n'est plus visible en clair dans la vue « Outline ».

Image non disponible

Bien entendu lors de la prochaine connexion, il sera nécessaire d'utiliser le nouveau mot de passe.

III-F-2. Création d'une entrée

Nous allons créer une nouvelle entrée dans la partition « dc=developpez,dc=com » qui a été créée précédemment.

Faire un clic droit sur la partition. Choisir « Nouveau »/« Nouvelle Entrée… ».

Image non disponible

Cliquer sur le bouton « Next > ».

Image non disponible

Sélectionner la classe « organizationalUnit » dans la liste et cliquer sur le bouton « Ajouter ». Puis cliquer sur le bouton « Next > ».

Image non disponible

Dans le RDN (Relative Distinguished Name), saisir que « ou » vaut « people ». Puis cliquer sur le bouton « Next > ».

Image non disponible

Cliquer sur le bouton « Finish ».

Image non disponible

La nouvelle entrée apparaît maintenant dans le « Navigateur LDAP ».

Image non disponible

Sur le même principe, il est possible de créer l'entrée ci-dessous (classe « inetOrgPerson »).

Image non disponible
Image non disponible
Image non disponible

III-F-3. Export LDIF

Nous allons exporter dans un fichier LDIF l'entrée « uid=rpouiller,dc=developpez,dc=com » que nous avons créée précédemment.

Faire un clic droit sur l'entrée et choisir « Export »/« Export LDIF... ».

Image non disponible

Cliquer sur le bouton « Next > ».

Image non disponible

Saisir le chemin du fichier LDIF. Puis cliquer sur le bouton « Finish ».

Image non disponible

III-G. Éditeur LDIF

Sélectionner « Open File… » le menu « File ».

Image non disponible

Sélectionner le fichier précédemment sauvé.

Image non disponible

Modifier le fichier comme ci-dessous et le sauver.

 
Sélectionnez
version: 1

dn: uid=testldif,ou=people,dc=developpez,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: person
objectClass: organizationalPerson
cn: test ldif
sn: ldif
uid: testldif
mail: test@ldif.com

III-H. Vue « Navigateur LDAP » (suite)

III-H-1. Import LDIF

Nous allons importer le ficher LDIF modifié dans le LDAP.

Faire un clic droit dans la vue « Navigateur LDAP » et choisir « Import »/« Import LDIF... ».

Image non disponible

Choisir le fichier et cliquer sur le bouton « Finish ».

Image non disponible

L'entrée a été importée.

Image non disponible

L'import de fichier LDIF peut également permettre de mettre à jour des données existantes (voir la case à cocher « Mettre à jour les données existantes » dans la fenêtre d'import ci-dessus).

III-H-2. Ajout d'un attribut

Nous allons ajouter un attribut à l'entrée LDAP que nous venons d'importer.

Une fois l'entrée sélectionnée dans le « Navigateur LDAP », faire un clic droit dans l'éditeur et sélectionner « Nouvel attribut… ».

Image non disponible

Sélectionner un « Type d'attribut » et cliquer sur le bouton « Finish ».

Image non disponible

Saisir la valeur et valider avec la touche « Entrée ».

Image non disponible

III-H-3. Suppression d'un attribut

Nous allons supprimer un attribut à l'entrée LDAP que nous venons d'importer.

Faire un clic droit sur l'attribut et sélectionner « Supprimer la valeur ».

Image non disponible

Cliquer sur le bouton « OK ».

Image non disponible

L'attribut a été supprimé.

Image non disponible

Normalement la fonctionnalité permet de supprimer une valeur d'attribut. Dans ce cas, l'attribut a été supprimé car c'était la seule valeur.

III-H-4. Suppression d'une entrée

Nous allons supprimer l'entrée LDAP que nous venons d'importer.

Faire un clic droit sur l'entrée et sélectionner « Supprimer l'entrée ».

Image non disponible

Cliquer sur le bouton « OK ».

Image non disponible

L'entrée a été supprimée.

Image non disponible

III-I. Vue « Logs de modifications »

La vue « Logs de modifications » permet de tracer les modifications dans le LDAP.

Image non disponible

III-J. Vue « Logs de recherches »

La vue « Logs de recherches » permet de tracer les recherches/consultations dans le LDAP.

Image non disponible

IV. APACHE DIRECTORY LDAP API

IV-A. Présentation

Apache Directory LDAP API est une API Java permettant d'accéder à un serveur LDAP (tous les types de serveur et pas seulement Apache Directory Server).

L'API permet de rechercher, consulter, modifier ou supprimer des entrées dans un LDAP.

IV-B. Téléchargement

Au moment de la rédaction de cet article, la version de l'API est « 1.0.0-M20 ». Le fichier contenant les bibliothèques nécessaires « apache-ldap-api-1.0.0-M20-bin.zip » est téléchargeable à l'adresse http://directory.apache.org/api/downloads.html.

Sinon, il est possible d'utiliser Maven avec la dépendance suivante :

 
Sélectionnez
<dependency>
    <groupId>org.apache.directory.api</groupId>
    <artifactId>api-all</artifactId>
    <version>1.0.0-M20</version>
</dependency>

IV-C. Lecture des entrées dans le LDAP

Le code Java suivant permet de visualiser l'entrée que nous avons ajoutée dans Apache Directory Studio.

 
Sélectionnez
package com.developpez.rpouiller;

import java.io.IOException;

import org.apache.directory.api.ldap.model.cursor.CursorException;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;

public class ConsultationLdapMain {

    public static void main(String[] args) throws LdapException, IOException, CursorException {
        final LdapConnection lLdapConnection = new LdapNetworkConnection("localhost", 10389);
        lLdapConnection.bind("uid=admin,ou=system", "nouveausecret");

        final EntryCursor lEntryCursor = lLdapConnection.search(
                                                    "ou=people,dc=developpez,dc=com", 
                                                    "(objectclass=*)", 
                                                    SearchScope.ONELEVEL, 
                                                    "*");

        for (final Entry lEntry : lEntryCursor) {
            System.out.println(lEntry);
        }

        lLdapConnection.unBind();
        lLdapConnection.close();
    }
}

Cela donne la trace suivante :

 
Sélectionnez
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Entry
    dn: uid=rpouiller,ou=people,dc=developpez,dc=com
    objectClass: organizationalPerson
    objectClass: person
    objectClass: inetOrgPerson
    objectClass: top
    uid: rpouiller
    sn: regis1512
    cn: Régis Pouiller

IV-D. Création d'une entrée dans le LDAP

Le code Java suivant permet de créer une entrée dans le serveur Apache Directory Server.

 
Sélectionnez
package com.developpez.rpouiller;

import java.io.IOException;

import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;

public class CreationLdapMain {

    public static void main(String[] args) throws LdapException, IOException {
        final LdapConnection lLdapConnection = new LdapNetworkConnection("localhost", 10389);
        lLdapConnection.bind("uid=admin,ou=system", "nouveausecret");

        lLdapConnection.add( 
                new DefaultEntry( 
                    "uid=test,ou=people,dc=developpez,dc=com",    // Distinguished Name
                    "ObjectClass: top",
                    "objectClass: inetOrgPerson",
                    "ObjectClass: person",
                    "objectClass: organizationalPerson",
                    "cn: nom courant",
                    "sn: surnom",
                    "uid: test"
                    ));

        lLdapConnection.unBind();
        lLdapConnection.close();
    }
}

On retrouve cette entrée dans le LDAP.

Image non disponible

IV-E. Modification d'une entrée dans le LDAP

Le code Java suivant permet de modifier une entrée dans le serveur Apache Directory Server.

 
Sélectionnez
package com.developpez.rpouiller;

import java.io.IOException;

import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
import org.apache.directory.api.ldap.model.entry.DefaultModification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;

public class ModificationLdapMain {

    public static void main(String[] args) throws LdapException, IOException {
        final LdapConnection lLdapConnection = new LdapNetworkConnection("localhost", 10389);
        lLdapConnection.bind("uid=admin,ou=system", "nouveausecret");

        lLdapConnection.modify(
                new Dn("uid=test,ou=people,dc=developpez,dc=com"),
                new DefaultModification(
                        ModificationOperation.REPLACE_ATTRIBUTE,
                        new DefaultAttribute("sn", "nouveau surnom")
                    ));

        lLdapConnection.unBind();
        lLdapConnection.close();
    }
}

On retrouve cette entrée dans le LDAP.

Image non disponible

IV-F. Suppression d'une entrée dans le LDAP

Le code Java suivant permet de supprimer une entrée dans le serveur Apache Directory Server.

 
Sélectionnez
package com.developpez.rpouiller;

import java.io.IOException;

import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;

public class SuppressionLdapMain {

    public static void main(String[] args) throws LdapException, IOException {
        final LdapConnection lLdapConnection = new LdapNetworkConnection("localhost", 10389);
        lLdapConnection.bind("uid=admin,ou=system", "nouveausecret");

        lLdapConnection.delete("uid=test,ou=people,dc=developpez,dc=com");

        lLdapConnection.unBind();
        lLdapConnection.close();
    }
}

La suppression est validée dans le LDAP.

Image non disponible

IV-G. Alternatives

Apache Directory LDAP API n'est pas la seule API Java permettant d'accéder à un serveur LDAP. Il y a l'API standard de Java (comme vu dans le II-D. Serveur embarquéServeur embarqué) et Spring LDAP.

IV-G-1. API standard de Java

L'API standard de Java permet d'accéder à un serveur LDAP.

 
Sélectionnez
package com.developpez.rpouiller;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

public class ApiStandardMain {

    public static void main(String[] args) throws NamingException {
        final Hashtable<String, String> lEnvironment = new Hashtable<String, String>();
        lEnvironment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        lEnvironment.put(Context.PROVIDER_URL, "ldap://localhost:10389/");
        lEnvironment.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
        lEnvironment.put(Context.SECURITY_CREDENTIALS, "nouveausecret");

        final LdapContext lLdapContext = new InitialLdapContext(lEnvironment, new Control[0]);
        final SearchControls lSearchControls = new SearchControls();
        lSearchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);

        final NamingEnumeration<SearchResult> lResultats = lLdapContext.search(
                "ou=people,dc=developpez,dc=com", "(objectclass=*)", lSearchControls);

        System.out.println("Résultat trouvé : ");
        while (lResultats.hasMore()) {
            System.out.println("\t " + lResultats.next().getName());
        }
    }
}

Cela donne la trace suivante :

 
Sélectionnez
Résultat trouvé : 
     uid=rpouiller

IV-G-2. Spring LDAP

Spring LDAP est une librairie Java simplifiant les opérations LDAP. Elle est basée sur JdbcTemplate.

Voici les dépendances Maven de l'API :

 
Sélectionnez
<dependency>
    <groupId>org.springframework.ldap</groupId>
    <artifactId>spring-ldap-core</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.ldap</groupId>
    <artifactId>spring-ldap-core-tiger</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

Voici la configuration Spring :

applicationContext.xml
Sélectionnez
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ldap="http://www.springframework.org/schema/ldap"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">

    <ldap:context-source url="ldap://localhost:10389"
        base="ou=people,dc=developpez,dc=com" username="uid=admin,ou=system" password="nouveausecret" />

    <ldap:ldap-template id="ldapTemplate" />

</beans>

Et finalement, la source d'une classe d'exemple :

 
Sélectionnez
package com.developpez.rpouiller;

import static org.springframework.ldap.query.LdapQueryBuilder.query;

import java.util.List;

import javax.naming.NamingException;
import javax.naming.directory.Attributes;

import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.query.LdapQuery;
import org.springframework.ldap.query.SearchScope;

public class SpringLdapMain {

    public static void main(String[] args) {
        final FileSystemXmlApplicationContext lApplicationContext = new FileSystemXmlApplicationContext("applicationContext.xml");

        final LdapTemplate lLdapTemplate = (LdapTemplate) lApplicationContext.getBean("ldapTemplate");

        final LdapQuery lLdapQuery = query().searchScope(SearchScope.ONELEVEL).where("objectClass").like("*");
        final List<String> lList = lLdapTemplate.search(lLdapQuery, new AttributesMapper<String>() {

            public String mapFromAttributes(final Attributes pAttributes) throws NamingException {
                return "uid=" + pAttributes.get("uid").get().toString();
            }
        
        });

        System.out.println("Résultat trouvé : ");
        for (final String lResultat : lList) {
            System.out.println("\t " + lResultat);
        }

        lApplicationContext.close();
    }
}

Cela donne la trace suivante :

 
Sélectionnez
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Résultat trouvé : 
     uid=rpouiller

V. CONCLUSION

Nous avons pu voir que le projet Apache Directory est une solution LDAP très intéressante (et surtout très complète). Au moment de la rédaction de l'article, le principal inconvénient du projet est d'être seulement au statut de milestone et de ne pas avoir de release pour les versions récentes. Mais le projet est très actif (M15 est la septième milestone du serveur pour l'année 2013). Il est également possible d'avoir recours aux dernières releases même si elles datent un peu : Apache Directory Server 1.5.7 (du 24 avril 2010, non maintenu), Apache Directory Studio 1.5.3 (du 30 mars 2010) et Apache LDAP API 0.1 (du 24 mars 2010).

VI. REMERCIEMENTS

Je remercie très sincèrement :

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2013 Régis POUILLER. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.