Interroger l’AD en PHP (4)

Nous avons mis en place pas mal d’éléments dans les articles précédents de cette passionnante série. Aujourd’hui, nous allons passer au cas pratique – et donc à la programmation – en créant un petit formulaire HTML, qui sera rempli avec les données de l’AD via une fonction Ajax appelant un script PHP ! Rassurez-vous, c’est beaucoup plus simple que ça en a l’air. Lancez votre éditeur de texte ou IDE préféré, accrochez vos ceintures et bretelles, et c’est parti  !

Élémentaire mon cher Watson

Voici les éléments que nous allons créer (et qui ne sont pas dans la table périodique de Mendeleïev) :

  1. Une page HTML comprenant un formulaire tout simple et une fonction Javascript
  2. Une page PHP qui s’occupera de la requête LDAP et renverra le résultat à la fonction Javascript, qui s’occupera de mettre à jour le formulaire

Le formulaire

Très basique, notre formulaire ne contiendra que quatre champs texte :

  1. Le premier servira à entrer le login
  2. Le second contiendra le nom de famille de l’utilisateur
  3. Le troisième contiendra son prénom
  4. Le quatrième contiendra son adresse email

Pas besoin de bouton pour lancer la fonction Javascript, on se servira simplement de l’événement onKeyUp() sur le premier champ : dans la fonction JS, une fois un certain nombre de caractères entrés et que l’utilisateur n’appuie plus sur une touche du claver, on lancera la requête Ajax.

 

La fonction Javascript

Déclenchée par l’événement onKeyUp(), la fonction vérifiera que le nombre de caractères minimum pour le champ login est atteint, et si c’est le cas, elle appellera notre script PHP (dans le cas contraire, elle ne fera rien). En fonction de la réponse obtenue, elle mettre à jour les autres champs (nom, prénom, mail) du formulaire ou affichera une erreur (c’est important la gestion des erreurs).

Le script PHP

Là aussi le script est basique, il se contentera d’un seul paramètre en entrée (envoyé par la méthode HTTP GET), à savoir le login. Il ira ensuite interroger l’AD avec la fonction RunLDAPQuery() que nous avons créé lors des épisodes précédents, puis écrira les résultats dans une chaîne formattée : nous nous servirons du séparateur “<|>” pour délimiter nos champs, ce qui permettra à la fonction JS de récupérer les bonnes données et de les coller aux bons endroits.

C’est parti mon kiki

(Rien à voir avec les bits dont je parlais hier et qui m’a valu une remarque lubrique de la part d’une femme mariée, ahem). Voici le code HTML du formulaire, qu’on ne peut guère faire plus moche, et que vous enregistrerez sur votre serveur web sous le nom test.html (comme c’est original) :

<!DOCTYPE HTML>
<html>
<head>
	<title>Test formulaire rempli par LDAP</title>
</head>
<body>
	<h1>Test formulaire rempli par LDAP</h1>
	<form>
		<p>Login &nbsp; <input type="text" id="login" name="login" size=10 maxlength=10/></p>
		<p>Nom &nbsp; <input type="text" id="nom" name="nom" size=40 maxlength=40/></p>
		<p>Pr&eacute;nom &nbsp; <input type="text" id="prenom" name="prenom" size=40 maxlength=10/></p>
		<p>Mail &nbsp; <input type="text" id="mail" name="mail" size=40 maxlength=40/></p>
	</form>
</body>
</html>
form1

Quand je vous dis que c’est moche…

 

Et maintenant le code de notre fonction, que nous allons mettre entre les balises <head> et </head> de  notre page HTML :

<script language="JavaScript">
	function ajaxLDAP()
	{
		var minlogin=8;
		var login=document.getElementById("login").value;
		if(login=="" || login.length<minlogin)
		{
			return false;
		}

		if (window.XMLHttpRequest)
		{
			// code pour IE7+, Firefox, Chrome, Opera, Safari
			xmlhttp=new XMLHttpRequest();
		}
		else
		{
			// code pour IE6, IE5, vous n'avez pas honte ?
			xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
		}

		xmlhttp.onreadystatechange=function()
		{
			if (xmlhttp.readyState==4 && xmlhttp.status==200)
			{
				response=xmlhttp.responseText;
				var php=response.split("<|>");

				/* alert(response);  */

				if(php[0]=="OK")
				{
					document.getElementById("nom").value=php[1];
					document.getElementById("prenom").value=php[2];
					document.getElementById("mail").value=php[3];
					if(php[4]=="1")
					{
						alert("Attention, ce compte apparaît comme désactivé dans l'AD !");
					}
				}
				else if(response=="NF")
				{
					alert("Attention, ce login n'a pas été trouvé dans l'AD...");
				}
				else if(response=="ERR")
				{
					alert("Impossible d'interroger l'AD.");
				}
				return false;
			}
		}

		xmlhttp.open("GET","ajaxldap.php?login="+login,true);
		xmlhttp.send();
	}
</script>

Que fait cette fonction ajaxLDAP() ?

  • Tout d’abord, la variable minlogin contient le nombre de caractères minimum pour le login. Vous pouvez modifier cette valeur comme bon vous semble pour l’adapter à votre AD
  • Ensuite, elle récupère la valeur du champ “login”
  • Elle teste cette valeur : si login est vide ou que sa taille est inférieure à 8 caractères, on retourne false (autrement dit, on ne fait rien)
  • Ensuite, si l’objet window.XMLHttpRequest existe dans le navigateur, on crée cet objet (il s’agit de l’objet Ajax lui-même)
  • Si cet objet n’existe pas, c’est qu’on est sous IE5 ou IE6, et dans ce cas on pallie à ce problème avec le contrôle ActiveX qui a exactement la même utilité
  • On crée ensuite une fonction sans nom qui sera appelée lorsque l’état de notre objet Ajax aura changé d’état (autrement dit, lorsqu’on aura reçu un réponse HTTP, quelle qu’elle soit, même si on ne s’occupe que du code 200 qui indique que tout s’est bien passé), et qui découpera la réponse avec le séparateur “<|>” pour remplir un tableau (nommé php) contenant les valeurs qu’elle assignera aux champs de notre formulaire, tout en gérant d’éventuelles erreurs ! Ouf !

Enfin le script PHP, que vous enregistrerez sous le nom ajaxldap.php dans le même répertoire que test.html :

  • On reprend les paramètres de connexion au serveur LDAP et la fonction RunLDAPQuery() que nous avons déjà vu précédemment
  • Le script écrit (via la commande echo) un code de retour (OK, ERR…) puis les informations que nous avons récupéré de l’AD dans l’ordre nom, prénom, mail et un flag indiquant si le compte est désactivé ou non (0 : non, 1 : oui)
<?php
// Nom ou adresse IP du contrôleur de domaine (précédé de ldap://)
$LDAPserver = "ldap://monjolidc";
// Utilisateur du domaine (user@domainfqdn) et surtout pas domain\user
$LDAPuser = "dede@lateur.laserforce.org";
// Mot de passe de l'utilisateur
$LDAPpwd = "password";
// Chemin FQDN où seront effectuées les recherches par défaut. Précisez les OU - organizational unit et DC - domain component ex : ou=toto,ou=titi,dc=domain,dc=com
$LDAPdefaultou = "OU=Lateur,dc=laserforce,dc=org";

function RunLDAPQuery($LDAPou,$LDAPquery)
{
	// En entrée :
	// $LDAPou = chaîne vide (utilisera $LDAPdefaultou) ou préciser le chemin de l'OU dans laquelle effectuer les recherches, ex: OU=Toto,OU=Titi,DC=domaine,DC=com
	// $LDAPquery = chaîne contenant le filtre à utiliser pour la recherche
	// En sortie :
	// Retourne un tableau multidimensionnel ($LDAPdata) ou false si le binding n'a pu se faire
	global $LDAPserver, $LDAPuser, $LDAPpwd, $LDAPdefaultou;
	$LDAPds=ldap_connect($LDAPserver);
	if(ldap_bind($LDAPds, $LDAPuser , $LDAPpwd)===true)
	{
		if($LDAPou=="")
		{
			$LDAPou=$LDAPdefaultou;
		}
		$LDAPsr=ldap_search($LDAPds, $LDAPou, $LDAPquery);
		$LDAPdata = ldap_get_entries($LDAPds, $LDAPsr);
		ldap_close($LDAPds);
		return $LDAPdata;
	}
	else
	{
		return false;
	}
}

if(isset($_GET["login"]))
{
	$login=$_GET["login"];
}
else
{
	echo "ERR"; // Erreur (pas de login fourni)
	exit;
}

$ldapres=@RunLDAPQuery("","(samaccountname=$login)");
if($ldapres!=false)
{
	if($ldapres["count"]!=0)
	{
		if (isset($ldapres[0]["sn"][0]))
		{
			$ldapuserlastname=$ldapres[0]["sn"][0];
		}
		else
		{
			$ldapuserlastname="";
		}

		if (isset($ldapres[0]["givenname"][0]))
		{
			$ldapuserfirstname=$ldapres[0]["givenname"][0];
		}
		else
		{
			$ldapuserfirstname="";
		}

		if (isset($ldapres[0]["mail"][0]))
		{
			$ldapusermail=$ldapres[0]["mail"][0];
		}
		else
		{
			$ldapusermail="";
		}

		if (isset($ldapres[0]["useraccountcontrol"][0]))
		{
			if($ldapres[0]["useraccountcontrol"][0] & 2) // voir https://support.microsoft.com/fr-fr/kb/305144
			{
				$ldapuserdisabled=1; // compte désactivé
			}
			else
			{
				$ldapuserdisabled=0;
			}
		}

		echo "OK<|>$ldapuserlastname<|>$ldapuserfirstname<|>$ldapusermail<|>$ldapuserdisabled";
		exit;
	}
	else
	{
		echo "NF"; // Not found, compte non trouvé
		exit;
	}
}
else
{
	echo "ERR"; // Erreur (échec de binding dans ce cas)
	exit;
}

Comme on ne s’attend qu’à un seul résultat (le login est censé être unique dans l’AD), on ne se casse pas la tête et on ne prend que le résultat d’index 0 du tableau $ldapres pour chaque propriété. Si une propriété est vide, on renvoie une chaîne vide (là aussi on ne se prend pas la tête), auquel cas le champ correspondant de notre formulaire restera tout aussi vide.

Notez le @ devant l’appel de la fonction RunLDAPQuery() : c’est pour éviter que PHP n’affiche une erreur ou un warning qui sera “écrit” avant notre chaîne. Si on affiche via une alerte Javascript la valeur de response, on se retrouve avec tout ce blabla avant “ERR”, ce que notre fonction Javascript ne sait pas traiter :

 

Mais j'en veux pas de ce warning moi

Mais j’en veux pas de ce warning moi

 

La variable $login est récupérée depuis l’index “login” du tableau associatif $_GET[], qui contient les paramètres envoyés dans l’URL (en effet, notre URL d’appel du script PHP est de la forme https://serveur/ajaxldap.php?login=valeur).

Il ne nous reste plus qu’à modifier un tout petit peu notre formulaire HTML pour que la modification du champ Login déclenche la fonction Javascript :

<p>Login &nbsp; <input type="text" id="login" name="login" size=10 maxlength=10 onKeyUp="ajaxLDAP();"></p>

Vous pouvez bien évidemment choisir l’événement onChange() plutôt que onKeyUp(), c’est vous qui voyez.

Maintenant que tout est prêt, il ne vous reste plus qu’à lancer votre navigateur et appeler la page test.html. Si tout est correctement configuré de votre côté (notamment les paramètres d’accès à votre serveur AD dans le script ajaxldap.php), vous devriez obtenir quelque chose de similaire à ceci après avoir entré un login valide :

Ça maaaaarche ! \o/

Ça maaaaarche ! \o/

Voilà c’est fini

Cette série d’articles est désormais terminée, j’espère que vous avez pris autant de plaisir à la lire que moi à l’écrire et que vous avez appris quelque chose. Comme je suis sympa, je vous mets la page HTML et le script PHP dans une archive ZIP que vous pouvez télécharger en cliquant sur le lien ci-dessous :

Ajaxldap.zip

Tchüss !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.