Open Source im professionellen Einsatz

LDAP-Anbindung in PHP-Anwendungen auf- oder nachrüsten

Zentral erfasst

,

Egal ob man eine eigene Webanwendung schreibt oder nachträglich eine freie Lösung aufbohren will: Die Benutzerinformationen in einem LDAP-Verzeichnis zu speichern schafft Login-Synergien und bringt Konsistenz in die eigene IT-Landschaft. Fehlt nur die LDAP-Authentifizierung.

LDAP hat sich als Standard für Benutzer- und Adresseninformationen etabliert und arbeitet in diesem Bereich effizienter als eine Datenbank. PHP bringt außerdem eine Schnittstelle für die Kommunikation mit dem Verzeichnisdienst mit, die einige Webanwendung für die Benutzerauthentifizierung einsetzen - leider jedoch nicht die Mehrheit. Dieser Artikel erläutert, wie sich eine LDAP-Anbindung selbst programmieren lässt.

Die installierte PHP-Version muss mit der Option »--with-ldap« kompiliert sein oder die LDAP-Extension als Erweiterung einbinden. Ob dies der Fall ist, zeigt die Ausgabe der Funktion »phpinfo()« (siehe Abbildung 1). Im PHP-Erweiterungs-Repository PEAR [1] gibt es außerdem die Klasse »auth()«, die den Umgang mit LDAP erleichtert [2]. Sie unterstützt nicht nur LDAP, sondern auch eine Authentifizierung über Datenbanken oder Passwortdateien und weitere Datenquellen. In Listing 1 ist zu sehen, wie der Entwickler LDAP auswählt.

Zeile 2 bindet die PEAR-Erweiterung ein. Zeile 9 erzeugt das für die Authentifizierung erforderliche PHP-Objekt mit den Parametern aus dem Array »$optionen[]«. Das sind die Adresse und der Port des LDAP-Servers (»localhost«, »389«), die eingesetzte Version des LDAP-Protokolls und die LDAP-Basisdomäne »dc=j-hoch-3,dc=de«.

Abbildung 1: Eine Extension bindet PHP an LDAP an, »phpinfo()« gibt Auskunft, ob die Erweiterung geladen oder einkompiliert ist.

Abbildung 1: Eine Extension bindet PHP an LDAP an, »phpinfo()« gibt Auskunft, ob die Erweiterung geladen oder einkompiliert ist.

Listing 1:
»Auth.php«

01 <?php
02   require_once "Auth.php";
03   $optionen = array('host' => 'localhost',
04                     'port' => '389',
05                     'version'= 3,
06                     'basedn' => 'dc=j-hoch-3, dc=de',
07                     'userattr' => 'uid',
08                     'useroc' => 'person');
09   $auth = new Auth('LDAP', $optionen, $loginFunction = 'Funktionsname', $showLogin = true);
10   //Starte Authentifizierung
11   $auth->start();
12 
13   if($auth->getAuth()){
14     //Quelltext für authentifizierte Benutzer
15   }
16   else{
17     //Quelltext für nicht authentifizierte Benutzer
18   }
19 
20   //Nutzer ausloggen
21   $auth->logout();
22 ?>

Spezialfall

In Zeile 8 teilt »'useroc' => 'person'« dem Auth-Objekt mit, dass es die Attribute der LDAP-Objektklasse »person« für die Suche verwenden soll. Es überschreibt die Standardeinstellung, bei der »PEAR::Auth« in der Objektklasse »posixAccount« sucht, die die Felder »gidNumber«, »homeDirectory« und »uidNumber« voraussetzt. Da eine Webanwendung diese nicht benötigt, vergleicht die Authentifizierung im Beispiel stattdessen das Feld »uid« (User ID). Auch der Common Name (»cn«) oder der Search Name (»sn«) kämen in Frage.

Hat der Parameter »$showLogin« in Zeile 9 den Wert »true«, erzeugt die PEAR-Erweiterung automatisch ein Login-Formular, wenn der Benutzer noch nicht eingeloggt ist. Über eine Funktion, die den HTML-Code für das Formular erzeugt, lässt sich dessen Aussehen steuern. Dabei ist darauf zu achten, dass das Formular Benutzername und Password per »$POST« über die Formularfelder »username« und »password« zurückgibt.

Listing 2 zeigt eine LDIF-Datei (LDAP Directory Interchange Format), dem Format, in dem LDAP seine Daten ablegt.Sie enthält zwei Beispielbenutzer, unter anderem mit den für die Authentifizierung nötigen Informationen. Im Beispiel speichern »dn:dc«, »uid« und »userpassword« die Login-Daten.

Listing 2:
LDIF-Datei

01 dn: cn=Falko Benthin,ou=editors,dc=j-hoch-3,dc=de
02 objectclass: top
03 objectclass: person
04 cn: Falko Benthin
05 sn: Benthin
06 uid: fbenthin
07 ou: editors
08 mail: fbenthin@j-hoch-3.de
09 l: Potsdam
10 postalcode: 14467
11 userpassword: geheim1
12 
13 dn: cn=Hans Hein,ou=editors,dc=j-hoch-3,dc=de
14 objectclass: top
15 objectclass: person
16 cn: Hans Hein
17 sn: Hein
18 uid: hhein
19 ou: editors
20 mail: hhein@j-hoch-3.de
21 l: Potsdam
22 postalcode: 14467
23 userpassword: geheim2

Der Aufruf der Methode »$auth->start()« in Zeile 11 von Listing 1 instanziiert das Auth-Objekt und authentifiziert einen Benutzer. Dazu führt die Methode eine anonyme Bindung mit dem LDAP-Server durch und prüft, ob es zu dem mit »username« übergebenen Wert unter dem für »userattr« festgelegten Feld einen Eintrag im LDAP-Verzeichnis gibt. Ist genau eine Person mit dem entsprechenden Eintrag vorhanden, versucht »Auth::start()« eine authentifizierte Bindung mittels des Distinguished Name und des im Formular übergebenen Passworts.

Stimmen alle Angaben überein, gilt die PHP-Session des Seitenbesuchers von nun an als authentifiziert. »$auth->getAuth()« liefert so lange den Status »true«, bis die Benutzersession über den in »php.ini« eingestellten Timeout verfällt oder der Benutzer aus der Session heraus »$auth->logout()« aufruft. Die Klassenvariable »$username« enthält den Benutzernamen, den Webanwendungen zur Laufzeit meist häufig abfragen.

Weiter geht's

Mit dem PEAR-Modul Auth ist also in PHP mit geringem Aufwand eine Authentifizierung gegen LDAP realisierbar. Damit ist die Aufgabe, eine Webanwendung für den LDAP-Einsatz aufzurüsten, aber noch nicht erledigt: Im PHP-Code sind jene Stellen durch Aufruf der Methode »getAuth()« zu ersetzen, in denen die Webanwendung in der für sie spezifischen Art prüft, ob der Benutzer angemeldet ist. Gleiches gilt auch für sämtliche Stellen, an denen die Software den Benutzernamen aus der Datenbank ausliest.

Wie hoch der Aufwand im konkreten Fall ausfällt, hängt davon ab, wie systematisch die Anwendung programmiert ist. Benutzt sie für die Authentifizierung durchgängig eine Funktion oder Methode, dann hält er sich in Grenzen, Eingriffe sind nur an wenigen Stellen im Code nötig. Zuverlässig sollte dies immer der Fall sein, wenn die Anwendung mehrere Datenbank-Backends unterstützt und diese also zwangsläufig über eine Abstraktionsschicht anspricht. E

Ein Debugger, der es erlaubt, den Code im Schrittmodus ablaufen zu lassen, ist ein gutes Mittel, um eine Anwendung zu verstehen. Am komfortabelsten geht dies in PHP mit Eclipse, den Erweiterungen PHP-Development-Tools [3] und dem kostenlosen Executable Debugger von Zend ([4], Abbildung 2). Eine freie Version gibt es von dem Debugger DBG [5], Xdebug ist unter der PHP-License verfügbar [6].

Abbildung 2: Eclipse, die PHP-Development-Tools und der Zend-Debugger bieten zusammen eine gute Starthilfe, um den Code einer PHP-Webanwendung zu verstehen.

Abbildung 2: Eclipse, die PHP-Development-Tools und der Zend-Debugger bieten zusammen eine gute Starthilfe, um den Code einer PHP-Webanwendung zu verstehen.

Diesen Artikel als PDF kaufen

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook