Comment Ca Marche - Communauté informatique  
   
Accueil - Encyclopédie informatiqueTélécharger l'encyclopédieContribuer à cet article

PHP - Connexion à un annuaire LDAP

Connexion à un serveur LDAP avec PHP Encyclopédie


Introduction à LDAP

PHP permet la connexion et l'envoi de requêtes sur un annuaire LDAP, c'est-à-dire un serveur permettant de stocker des informations de manière hiérarchique.

Un serveur LDAP est conçu pour être capable de gérer les opérations suivantes :

  • établir la connexion avec l'annuaire
  • rechercher des entrées
  • comparer des entrées
  • ajouter des entrées
  • modifier des entrées
  • supprimer des entrées
  • annuler ou abandonner une opération
  • fermer la connexion avec l'annuaire
Ainsi PHP fournit un ensemble de fonctions (pour peu que le module LDAP soit installé) permettant de réaliser ces opérations. Ces fonctions seront explicitées au long de l'article.

Avant de commencer, il faut installer le module LDAP pour le langage PHP. Ce module ajoute un certain nombre de fonctions qui débutent par « ldap_ » et qui permettent d'interfacer le serveur. En effet, par défaut, PHP n'est pas livré avec le support LDAP. Si vous n'installez pas le module et que vous tentez d'utiliser les commandes concernant LDAP, vous obtiendrez le message d'erreur suivant :
Fatal error: Call to unsupported or undefined function ldap_connect()
inrpm -ivh /home/httpd/html/ldap/consulte.php3 on line x
Il est possible de se procurer ces bibliothèques sur le serveur de l'Université du Michigan (ldap-3.3 package) ou chez Netscape (Netscape Directory SDK).

Séquence d'interrogation avec LDAP

L'interrogation d'un serveur LDAP avec PHP se fait selon une séquence simple, nécessitant un nombre peu élevé de fonctions spécialisées. La séquence basique est la suivante :

  • Etablissement de la connexion avec le serveur LDAP
  • Liaison et authentification sur le serveur (appelé bind en anglais)
  • Recherche d'une entrée (ou bien une autre opération)
  • Exploitation des résultats (uniquement dans le cas d'une recherche)
  • Fermeture de la connexion

Connexion au serveur LDAP

Avant de pouvoir interroger le serveur LDAP, il est essentiel d'initier la connexion. Pour cela l'interpréteur PHP a besoin de connaître quelques renseignements relatifs à l'annuaire :

  • L'adresse du serveur
  • Le port sur lequel le serveur fonctionne
  • La racine de l'annuaire
  • Le login de l'utilisateur (généralement root) ainsi que son mot de passe
<?
	// Fichier de configuration pour l'interface PHP
   //  de notre annuaire LDAP
   $server = "localhost";

   $port = "389";

   $racine = "o=commentcamarche, c=fr";

   $rootdn = "cn=ldap_admin, o=commentcamarche, c=fr";

   $rootpw = "secret";

?>
On définit donc cinq variables pour caractériser le serveur LDAP : le nom du serveur, le port (389 par défaut), la racine supérieure de l'arborescence, la chaîne de connexion pour l'administrateur ainsi que son mot de passe.

La première fonction à utiliser est la fonction ldap_connect() permettant d'établir une liaison avec le serveur. Sa syntaxe est la suivante :

int ldap_connect ([string hostname [, int port]])
Cette fonction admet en paramètre le nom du serveur (éventuellement le port. Par défaut le port est 389). En cas d'échec cette fonction retourne 0 sinon elle retourne un entier permettant d'identifier le serveur et nécessaire dans les fonctions suivantes.

Voici un exemple de connexion au serveur :

<?
echo "Connexion...<br>";

$ds=ldap_connect($server);

?>

Toutefois cette opération n'est pas suffisante pour pouvoir exécuter des opérations sur le serveur LDAP. En effet, il est nécessaire d'initier la liaison (en anglais to bind) avec le serveur LDAP à l'aide de la fonction ldap_bind() dont la syntaxe est la suivante :

int ldap_bind (int identifiant [, string bind_rdn [, string bind_password]])
Cette fonction attend en paramètre l'identifiant du serveur retourné ainsi qu'éventuellement le Nom distingué relatif de l'utilisateur (RDN - Relative Distinguished Name) et son mot de passe. Si l'utilisateur et le mot de passe ne sont pas précisés, la connexion se fait de manière anonyme.

La déconnexion du serveur LDAP se fait tout naturellement par la fonction ldap_close() avec la syntaxe suivante :

int ldap_close (int identifiant)
Cette fonction est similaire à la fonction ldap_unbind().

Voici un exemple complet de connexion et de déconnexion à un serveur LDAP :

<?
   // Fichier de configuration pour l'interface PHP
   //  de notre annuaire LDAP
   $server = "localhost";

   $port = "389";

   $racine = "o=commentcamarche, c=fr";

   $rootdn = "cn=ldap_admin, o=commentcamarche, c=fr";

   $rootpw = "secret";

echo "Connexion...<br>";

$ds=ldap_connect($server);

if ($ds==1)
	 {
		// on s'authentifie en tant que super-utilisateur, ici, ldap_admin
		$r=ldap_bind($ds,$rootdn,$rootpw);

	// Ici les opérations à effectuer
	echo "Déconnexion...<br>";

	ldap_close($ds);

	 }
else {
	echo  "Impossible de se connecter au serveur LDAP";

	 }
?>

Exécution des opérations

Ajouter une entrée avec ldap_add()

La fonction ldap_add() permet d'ajouter des entrées à un annuaire LDAP auquel on s'est préalablement connecté (et lié). Voici sa syntaxe :

int ldap_add (int identifiant, string dn, array entry)
La fonction ldap_add() admet en paramètre l'identifiant du serveur LDAP retourné par la fonction ldap_connect() ainsi que le nom distingué de l'entrée (c'est-à-dire son emplacement dans l'annuaire) et un tableau contenant l'ensemble des valeurs des attributs de l'entrée.

Lorsqu'un attribut est multivalué (c'est-à-dire lorsqu'un attribut est lui-même composé de plusieurs valeurs), celles-ci sont indexées dans une case du tableau (les indices du tableau commencent à 0). Dans l'exemple ci-dessous par exemple, l'attribut "mail" possède plusieurs valeurs :

<?php
$ds=ldap_connect($server);  // On suppose que le serveur LDAP est sur cet hote
if ($ds) {
	$r=ldap_bind($ds,$rootdn,$rootpw);

	// preparation des données
	$entry["cn"]="Pillou";

	$entry["sn"]="Jean-Francois";

	$entry["mail"][0]="webmaster@commentcamarche.net";

	$entry["mail"][1]="Jeff@commentcamarche.net";

	$entry["objectclass"]="person";

	// Ajout des données dans l'annuaire
	$r=ldap_add($ds, "cn=Jean-Francois Pillou, o=commentcamarche, c=fr", $entry);

	ldap_close($ds);

} else {
	echo "Connexion au serveur LDAP impossible";

}

?>

Comparer une entrée avec ldap_compare()

La fonction ldap_compare() permet de comparer la valeur d'un attribut d'une entrée de l'annuaire LDAP, auquel on s'est préalablement connecté (et lié), à une valeur passée en paramètre. Voici la syntaxe de la fonction ldap_compare() :

int ldap_compare (int identifiant, string dn, string attribut, string valeur)
La fonction ldap_compare() admet en paramètre l'identifiant du serveur LDAP retourné par la fonction ldap_connect(), le nom distingué de l'entrée (c'est-à-dire son emplacement dans l'annuaire) ainsi que le nom de l'attribut de l'entrée et la valeur à laquelle on veut comparer sa valeur dans l'annuaire.

En cas d'erreur, la fonction ldap_compare() renvoie la valeur -1, en cas de réussite elle renvoie TRUE, enfin dans le cas contraire elle renvoie FALSE.

L'exemple suivant (largement inspiré de celui de www.php.net) montre comment comparer un mot de passe avec celui stocké dans l'annuaire pour un utilisateur donné  :

<?php
$ds=ldap_connect($server);

if ($ds) {
	$r=ldap_bind($ds,$rootdn,$rootpw);

	// preparation des données
	$dn="cn=Pillou Jean-Francois, o=commentcamarche,c=fr";

	$valeur="MonMot2Passe";

	$attribut="password";

	// Comparaison du mot de passe à celui dans l'annuaire
	$resultat=ldap_compare($ds, $dn, $attribut, $valeur);

	if ($resultat == -1) {
	echo "Erreur:".ldap_error($ds);

	}
	elseif ($resultat == TRUE) {
	echo "Le mot de passe est correct";

	}
	else ($resultat == FALSE) {
	echo "Le mot de passe est erronné...";

	}
	ldap_close($ds);

} else {
	echo "Connexion au serveur LDAP impossible";

}

?>

Notez l'utilisation de la fonction ldap_error() sur laquelle nous reviendrons ultérieurement pour afficher les détails de l'erreur !

Supprimer une entrée avec ldap_delete()

La fonction ldap_delete() permet de supprimer des entrées d'un annuaire LDAP. Voici sa syntaxe :

int ldap_delete (int identifiant, string dn)
La fonction ldap_delete() admet uniquement deux paramètres :
  • l'identifiant du serveur LDAP retourné par la fonction ldap_connect()
  • le nom distingué de l'entrée à supprimer.
Une fois de plus, cette fonction renvoie TRUE en cas de réussite, FALSE en cas d'échec.

L'exemple suivant illustre la suppression d'un élément de l'annuaire :

<?php
$ds=ldap_connect($server);  // On suppose que le serveur LDAP est sur cet hote
if ($ds) {
	$r=ldap_bind($ds,$rootdn,$rootpw);

	// preparation des données
	$dn="Pillou Jean-Francois,o=commentcamarche,c=fr";

	// Supression de l'entrée de l'annuaire
	$r=ldap_delete($ds, $dn);

	ldap_close($ds);

} else {
	echo "Connexion au serveur LDAP impossible";

}

?>

Modifier une entrée avec ldap_modify()

La fonction ldap_modify() permet de modifier une entrée de l'annuaire LDAP. Sa syntaxe est la même que celle de la fonction ldap_add() :

int ldap_modify (int identifiant, string dn, array entry)
La fonction ldap_modify() admet en paramètre l'identifiant du serveur LDAP retourné par la fonction ldap_connect() ainsi que le nom distingué de l'entrée (c'est-à-dire son emplacement dans l'annuaire) et un tableau contenant l'ensemble des valeurs des attributs de l'entrée à modifier.

Lorsqu'un attribut est multivalué (c'est-à-dire lorsqu'un attribut est lui-même composé de plusieurs valeurs), celles-ci sont indexées dans une case du tableau (les indices du tableau commencent à 0). Dans l'exemple ci-dessous par exemple, l'attribut "mail" possède plusieurs valeurs :

<?php
$ds=ldap_connect($server);  // On suppose que le serveur LDAP est sur cet hote
if ($ds) {
	$r=ldap_bind($ds,$rootdn,$rootpw);

	// preparation des données
	$entry["cn"]="Pillou";

	$entry["sn"]="Jean-Francois";

	$entry["mail"][0]="webmaster@commentcamarche.net";

	$entry["mail"][1]="Jeff@commentcamarche.net";

	$entry["objectclass"]="person";

	// Ajout des données dans l'annuaire
	$r=ldap_modify($ds, "cn=Jean-Francois Pillou, o=commentcamarche, c=fr", $entry);

	ldap_close($ds);

} else {
	echo "Connexion au serveur LDAP impossible";

}

?>

Rechercher une entrée avec ldap_search()

La recherche d'entrée dans l'annuaire est sans aucun doute la fonction la plus utile parmi les fonctions LDAP de PHP¨car un annuaire est prévu pour être plus souvent sollicité en lecture (recherche) qu'en écriture (ajout/suppression/modification).

La fonction ldap_search() permet de rechercher une ou plusieurs entrées de l'annuaire LDAP à l'aide du DN de base, c'est-à-dire le niveau de l'annuaire à partir duquel la recherche est effectuée, ainsi qu'un filtre représentant le type de recherche que l'on désire effectuer. Sa syntaxe est la suivante :

int ldap_search (int identifiant, string base_dn,
	string filter [, array attributs [, int attrsonly [,
	int sizelimit [, int timelimit [, int deref]]]]])
La fonction ldap_search() admet en paramètre l'identifiant du serveur LDAP retourné par la fonction ldap_connect() ainsi que le nom distingué du dossier de base (c'est-à-dire celui à partir duquel la recherche doit s'effectuer) et le filtre de la recherche. La fonction ldap_search() est par défaut configurée avec l'option de récursivité LDAP_SCOPE_SUBTREE ce qui signifie que la recherche se fait dans toutes les branches filles du dossier de base.

Le paramètre attributs permet de restreindre les attributs et les valeurs retournées, c'est-à-dire qu'il s'agit d'un tableau contenant le nom des attributs (chaînes de caractères) des attributs que l'on désire utiliser. Par défaut l'intégralité des attributs des entrées est renvoyée par le serveur, ce qui peut donner un nombre de données très important.

Le paramètre attrsonly permet de demander à l'annuaire de retourner uniquement les types d'attributs et non leurs valeurs lorsqu'il vaut 1. Par défaut (ou lorsque ce paramètre vaut 0) les types des attributs ainsi que leurs valeurs sont retournés par le serveur.

Le sixième paramètre sizelimit comme son nom l'indique permet de limiter le nombre maximum de résultat retourné par l'annuaire afin de réduire le volume des données retournées. Il faut noter que si le serveur est configuré pour retourner moins de résultats, une valeur supérieure de l'attribut ne permettra pas de dépasser la valeur inscrite dans la configuration du serveur. La valeur 0 indique qu'aucune limite autre que celle imposée par le serveur n'est définie.

Le septième paramètre timelimit permet de limiter le temps maximal de la recherche pris par le serveur. Il faut noter que si le serveur est configuré pour retourner moins de résultats, une valeur supérieure de l'attribut ne permettra pas de dépasser la valeur inscrite dans la configuration du serveur. La valeur 0 indique qu'aucune limite autre que celle imposée par le serveur n'est définie.

Enfin le huitième paramètre deref permet d'indiquer selon sa valeur la façon de procéder avec les alias lors de la recherche. Les valeurs possibles de ce paramètre sont les suivantes :

  • LDAP_DEREF_NEVER : les alias ne sont jamais déréférencés. Il s'agit de la valeur par défaut.
  • LDAP_DEREF_SEARCHING : les alias sont déréférencés uniquement pendant la recherche et non pendant leur localisation.
  • LDAP_DEREF_FINDING : les alias sont déréférencés uniquement pendant leur localisation et non lors de la recherche.
  • LDAP_DEREF_ALWAYS : les alias sont toujours déréférencés.

L'exemple suivant permet de connaître le nombre de résultats retournés pour une recherche d'une personne dont le nom ou le prenom commence par la chaîne $person passée en paramètre :

<?php
$ds=ldap_connect($server);  // On suppose que le serveur LDAP est sur cet hote
if ($ds) {
	$r=ldap_bind($ds,$rootdn,$rootpw);

	$dn = "o=commentcamarche, c=fr";

	$filtre="(|(sn=$person*)(cn=$person*))";

	$restriction = array( "cn", "sn", "mail");

	$sr=ldap_search($ds, $dn, $filtre, $restriction);

	$info = ldap_get_entries($ds, $sr);

	print $info["count"]." enregistrements trouves

"; ldap_close($ds); } else { echo "Connexion au serveur LDAP impossible"; } ?>

Toutefois, une fois l'opération de recherche effectuée, il s'agit d'exploiter les résultats obtenus. Ainsi, la majeure partie des fonctions LDAP ont pour but le traitement des résultats de la recherche.
Dans l'exemple ci-dessus, la fonction ldap_get_entries() permet de récupérer des informations sur les entrées retournées par la fonction ldap_search().

Traitement des résultats

De nombreuses fonctions LDAP permettent d'exploiter les résultats renvoyés par la fonction ldap_search(). Ces fonctions ont un nom commençant généralement par ldap_get_ suivi du nom de l'élément à récupérer :

  • ldap_get_dn() permet de récupérer le DN de l'entrée
  • ldap_get_entries() permet de récupérer l'ensemble des entrées
  • ldap_get_option() permet de récupérer la valeur d'une option
  • ldap_get_values() permet de récupérer toutes les valeurs d'une entrée
  • ldap_get_values_len() permet de récupérer les valeurs binaires d'une entrée
  • ldap_count_entries() permet de récupérer le nombre d'entrées retournées par la fonction de recherche

Récupérer le nombre d'entrées retournées

La fonction ldap_count_entries() permet de connaître le nombre d'entrées retournées par la fonction ldap_search(). Sa syntaxe est la suivante :

int ldap_count_entries (int link_identifier, int result_identifier)
La fonction ldap_count_entries() admet en paramètre l'identifiant du serveur LDAP retourné par la fonction ldap_connect() ainsi que l'identifiant du résultat retourné par la fonction ldap_search() et retourne un entier représentant le nombre d'entrées stockées dans le résultat de la recherche.

Voici un exemple d'utilisation :

<?php
$ds=ldap_connect($server);  // On suppose que le serveur LDAP est sur cet hote
if ($ds) {
	$r=ldap_bind($ds,$rootdn,$rootpw);

	$dn = "o=commentcamarche, c=fr";

	$filtre="(|(sn=$person*)(cn=$person*))";

	$restriction = array( "cn", "sn", "mail");

	$sr=ldap_search($ds, $dn, $filtre, $restriction);

	$nombre = ldap_count_entries($ds, $sr);

	print $nombre." enregistrements trouves

"; ldap_close($ds); } else { echo "Connexion au serveur LDAP impossible"; } ?>

Récupérer les entrées retournées

La fonction ldap_get_entries() permet de récupérer l'ensemble des entrées retournées par la fonction ldap_search() ainsi que de lire les attributs associés et leur(s) valeur(s).
Sa syntaxe est la suivante :

array ldap_get_entries (int link_identifier, int result_identifier)
La fonction ldap_get_entries() admet en paramètre l'identifiant du serveur LDAP retourné par la fonction ldap_connect() ainsi que l'identifiant du résultat retourné par la fonction ldap_search() et retourne un tableau multidimensionnel contenant le résultat de la recherche, c'est-à-dire le DN et le nom de l'entrée ainsi que la ou les valeurs de chacune d'entre-elles.

La structure du tableau retourné (on supposera qu'il se trouve dans la variable $entrees) est la suivante :

  • $entrees["count"] : nombre d'entrées dans le résultat
  • $entrees[0] : détail de la première entrée
  • $entrees[i]["dn"] : DN de la ième entrée
  • $entrees[i]["count"] : nombre d'attributs de la ième entrée
  • $entrees[i][j] : valeur du jème attribut de la ième entrée
  • $entrees[i]["attribut"] : valeur de l'attribut nommé "attribut" de la ième entrée (pour un attribut multivalué)
  • $entrees[i]["attribut"]["count"] : Nombre de valeurs du jème attribut de la ième entrée (pour un attribut multivalué)
  • $entrees[i]["attribut"][j] : Jème valeur de l'attribut nommé "attribut" de la ième entrée (pour un attribut multivalué)

Les noms des attributs dans le tableau associatif sont en minuscules, ainsi l'attribut givenName devra être écrit givenname (par exemple $entrees[i]["givenname"])

Voici un exemple d'utilisation :

<?php
$ds=ldap_connect($server);  // On suppose que le serveur LDAP est sur cet hote
if ($ds) {
	$r=ldap_bind($ds,$rootdn,$rootpw);

	$dn = "o=commentcamarche, c=fr";

	$filtre="(|(sn=$person*)(cn=$person*))";

	$restriction = array( "cn", "sn", "mail");

	$sr = ldap_search($ds, $dn, $filter);

	echo "Le nombre d'entrées retourné est de ".ldap_count_entries($ds,$sr)."<br>";

	   echo  "Récupération des entrées ...";

	   $info = ldap_get_entries($ds, $sr);

	   echo  "Affichage des données des ".$info["count"]. " entrées trouvées :";

	   for ($i=0; $i<$info["count"]; $i++)
		   {
		   echo  "<p align="justify">";

		   echo  "Le dn (Distinguished Name) est: ". $info[$i]["dn"] ."<br>";

		   echo  "Nom (sn) : ". $info[$i]["sn"][0] . "<br>";

		   echo  "Prénom (cn) : ". $info[$i]["cn"][0] . "<br>";

		   for($j=0;$j<$info[$i]["mail"]["count"];$j++) {
		   	echo  "Email numéro $j: ". $info[$i][ "mail"][$j] ."<br>";

		}
		   }
	   echo  "<p> ... Fermeture de la connexion";

	ldap_close($ds);

} else {
	echo "Connexion au serveur LDAP impossible";

}

?>

Notez que pour récupérer uniquement le nombre de résultats total, il est préférable d'utiliser la fonction ldap_count_entries() que de passer par la fonction ldap_get_entries() puis $entrees["count"]

Plus d'informations

  • Pour plus d'informations sur LDAP, reportez-vous à la section consacrée à ce sujet
  • Pour plus d'informations sur l'interfaçage d'un annuaire LDAP, reportez-vous au site de référence PHP.net
  • PhpLdapAdmin, une application en PHP permettant de gérer votre annuaire LDAP

Article écrit par Jean-François Pillou

Trucs & astuces pertinents trouvés dans la base de connaissances

01/01 03h06 Notice: Undefined index: (Langages)
29/12 16h39 Afficher facilement le code php/xhtml de vos pages (Webmaster)
28/12 00h03 Récupérer login et mot de passe passés par un .htaccess (PHP)
08/12 22h42 Les ressemblances à ne pas confondre (PHP)
02/12 16h02 Vérifier une adresse électronique (format du mail) (PHP)
22/11 23h51 Rediriger sur une autre page (redirection) (PHP)
18/11 01h10 Fonction mail() (PHP)
11/11 01h39 Coloration syntaxique dans vos pages web (Webmaster)
27/10 00h14 Transformer une URL en lien hypertexte cliquable (PHP)
22/09 18h56 Connexion à une base Oracle en php (Oracle)
PHP LDAP Plus d'astuces sur « PHP LDAP »

Discussions pertinentes trouvées dans le forum

23/08 12h14 php ldap ldap 3.3 package [PHP/LDAP]LDAP-3.3 package Webmastering 23/08 16h27->StreM4
07/06 17h27 header.php footer.php ldap admin header.php footer.php ??? ldap admin Webmastering 09/06 22h11->Dreamer18
23/07 12h15 php ldap récupérer tous attributs [PHP/LDAP] - Récupérer TOUS les attributs Webmastering 23/07 17h29->vince349
01/09 13h26 php ldap active directory php + ldap sur active directory Webmastering 01/08 17h01->huvo9
03/07 17h05 php module ldap [PHP] Module LDAP Développement 11/07 13h29->KHALFI5
07/08 15h23 re modules ldap php retrouver les modules LDAP pour PHP Webmastering 09/08 09h48->tomyh3
28/04 11h51 php ldap accents [PHP <-> LDAP] Problème de d'accents Développement 28/04 20h57->Jack_le_Boulet2
01/07 18h19 modification ldap php modification ldap en php Webmastering 03/07 16h08->Pascal1
14/01 16h10 caractères spéciaux ldap php Caractères Spéciaux et Ldap et Php Webmastering 01/10 10h26->dom1
07/10 19h27 compatibilité php annuaire ldap Compatibilité entre php et l'annuaire LDAP Internet 30/10 08h05->damien1
Discussion fermée Problème résolu PHP LDAP Plus de discussions sur « PHP LDAP »

Ce document intitulé « PHP - Connexion à un annuaire LDAP » issu de l'encyclopédie informatique Comment Ça Marche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.