EinleitungMinimale Funktionalität
Im Moment ist diese Klasse nur dafür gedacht, die beschränkte Funktionalität zu bieten,
die für Zend_Auth_Adapter_Ldap
nötig ist. Weiterführende Verwendungsmöglichkeiten wie das Suchen, Erstellen,
Bearbeiten oder Umbenennen von Objekten im Verzeichnis werden im Moment nicht
unterstützt und werden zu einem späteren Zeitpunkt hinzugefügt werden.
Zend_Ldap ist eine Klasse, mit der LDAP-Operationen, wie das
Durchsuchen, das Bearbeiten oder die Bindung an Einträge im LDAP-Verzeichnis, durchgeführt
werden können.
Beschreibung
Diese Komponente besteht im Moment aus zwei Klassen, Zend_Ldap
und Zend_Ldap_Exception. Ein
Zend_Ldap-Objekt repräsentiert konzeptionell die Bindung an einen
einzelnen LDAP server. Die Parameter für diese Bindung können explizit oder in der form
eines Optionen-Arrays angegeben werden.
Die Verwendung von Zend_Ldap hängt von der Art Ihres LDAP-Servers
ab und kann am besten mit einigen einfachen Beispielen erklärt werden.
Wenn Sie OpenLDAP benutzen, wäre ein einfaches Beispiel das Folgende (Beachten Sie:
Die Option bindRequiresDn ist wichtig, wenn Sie nicht
Microsoft Active Directory benutzen):
's0.foo.net',
'username' => 'CN=user1,DC=foo,DC=net',
'password' => 'pass1',
'bindRequiresDn' => true,
'accountDomainName' => 'foo.net',
'baseDn' => 'OU=Sales,DC=foo,DC=net',
);
$ldap = new Zend_Ldap($options);
$acctname = $ldap->getCanonicalAccountName('abaker',
Zend_Ldap::ACCTNAME_FORM_DN);
echo "$acctname\n";
]]>
Wenn Sie Microsoft Active Directory nutzen, sollte das folgende Beispiel funktionieren:
'dc1.w.net',
'useStartTls' => true,
'username' => 'user1@w.net',
'password' => 'pass1',
'accountDomainName' => 'w.net',
'accountDomainNameShort' => 'W',
'baseDn' => 'CN=Users,DC=w,DC=net',
);
$ldap = new Zend_Ldap($options);
$acctname = $ldap->getCanonicalAccountName('bcarter',
Zend_Ldap::ACCTNAME_FORM_DN);
echo "$acctname\n";
]]>
Beachten Sie, dass wir die Methode getCanonicalAccountName() hier nur
benutzen, um den Domain-Name des Accounts 'bcarter' zu erhalten, weil das so ziemlich
alles von dem wenigen Code, der im Moment in dieser Klasse vorhanden ist, verwendet.
Automatische Normalisierung des Benutzernamens bei der Server-Bindung
Wenn bind() mit einem nicht-DN-konformen Benutzernamen aufgerufen wird
aber bindRequiresDNTRUE ist und kein Benutzername in
DN-Form als Option angegeben wird, wird die Server-Bindung fehlschlagen. Wenn
allerdings ein Benutzername in DN-Form im Optionen-Array übergeben wurde, wird
Zend_Ldap sich zuerst mit diesem Benutzernamen an den Server
binden, den Account-Domain Name für den Benutzernamen, der bind()
suchen und sich dann neu mit diesem DN verbinden.
Dieses Verhalten ist wichtig für Zend_Auth_Adapter_Ldap, das
den eingegebenen Benutzernamen direkt an bind() weiterleitet.
Das folgende Beispiel zeigt, wie der nicht DN-konforme Benutzername
'abaker' mit bind() benutzt werden kann:
's0.foo.net',
'username' => 'CN=user1,DC=foo,DC=net',
'password' => 'pass1',
'bindRequiresDn' => true,
'accountDomainName' => 'foo.net',
'baseDn' => 'OU=Sales,DC=foo,DC=net',
);
$ldap = new Zend_Ldap($options);
$ldap->bind('abaker', 'moonbike55');
$acctname = $ldap->getCanonicalAccountName('abaker',
Zend_Ldap::ACCTNAME_FORM_DN);
echo "$acctname\n";
]]>
Der Aufruf von bind() in diesem Beispiel erkennt dass der Benutzername
'abaker' nicht in DN-Form ist und dass bindRequiresDnTRUE ist, verwendet 'CN=user1,DC=foo,DC=net' und
'pass1' zum Verbinden, empfängt den DN für 'abaker',
löst die Bindung und bindet sich dann neu mit dem jetzt bekannten
'CN=Alice Baker,OU=Sales,DC=foo,DC=net'.
Zend_Ldap Optionen
Die Zend_Ldap-Komponente akzeptiert ein Array von Optionen,
das entweder im Konstruktor oder der Methode setOptions() übergeben
werden kann. Folgende Optionen sind möglich:
Zend_Ldap OptionenNameBeschreibunghost
Host-Name des LDAP-Servers, wenn er nicht in connect()
überschrieben wird. (kann auch verwendet werden, wenn die Komponente
versucht, Benutzernamen in bind() zu normalisieren).
port
Port des LDAP-Servers, wenn er nicht in connect()
überschrieben wird.
useStartTls
Ob der LDAP-Client TLS (auch SSL-v2) verschlüsselte Übertragung
verwenden soll. Der Wert TRUE ist auf jeden Fall in
Produktivumgebungen empfohlen, damit Passwörter nicht im Klartext
übertragen werden. Der Standardwert ist FALSE, weil Server
fast immer verlangen, dass ein Verschlüsselungszertifikat
nachinstalliert wird.
useSsl
Ob der LDAP Client SSL verschüsselte Übertragung unterstützen sollten
oder nicht. Die useSsl und useStartTls
Optionen sind gegenseitig exklusiv.
username
Der Standard-Benutzername. Bei manchen Servern muss dieser in DN-Form
vorliegen.
password
Das Passwort des Standard-Benutzernamens.
bindRequiresDn
Wenn dieser WertTRUE ist, wird
Zend_Ldap den Domain-Name für den Account, der
zur Bindung genutzt wird, suchen, wenn der Benutzername noch nicht in
DN-Form ist. Der Standardwert ist FALSE.
baseDn
Der Standard-DN, unter dem gesucht wird (bspw. Accounts). Diese Option
wird für die meisten Account-Bezogenen Vorgänge benötigt und sollte
den DN beinhalten, unter dem die Accounts liegen.
accountCanonicalForm
Eine Integerzahl, die die Art angibt, in der Account-Namen normalisiert
werden. Schauen Sie für mehr Informationen in die Tabelle
Accountnamen-Normalisierung weiter unten.
accountDomainName
Der vollqualifizierte Domain-Name, für den der LDAP-Server eine
Autorität ist.
accountDomainNameShort
Der 'Kurz'-Domain-Name für den der LDAP-Server eine Autorität ist.
Wird normalerweise in Windows-Netzwerken genutzt, um NetBIOS-Namen zu
definieren, kann aber auch von Nicht-AD-Servern genutzt werden.
accountFilterFormat
Der LDAP-Suchfilter, der verwendet wird, um Accounts zu suchen. Dieser
String ist ein Ausdruck im Stil von printf(),
der ein '%s' enthalten muss, das durch den Benutzernamen
ersetzt wird. Der Standardwert ist
'(&(objectClass=user)(sAMAccountName=%s))', es sei denn
bindRequiresDn ist TRUE. In diesem Fall ist
der Standardwert
'(&(objectClass=posixAccount)(uid=%s))'.
Wenn eigene Schemata benutzt werden, muss diese Option vielleicht
geändert werden.
allowEmptyPassword
Einige LDAP Server können so konfiguriert werden das Sie ein leeres
Passwort als anonyme Bindung akzeptieren. Dieses Verhalten ist fast
immer unerwünscht. Aus diesem Grund sind leere Passwörter explizit nicht
erlaubt. Wenn dieser Wert auf TRUE gesetzt wird ist die
Übermittlung eines leeres Passwortes wärend des Bindens erlaubt.
optReferrals
Auf TRUE gesetzt, zeigt diese Option dem LDAP Client das
Referenzen gefolgt werden soll. Der Standardwert ist FALSE.
Normalisierung von Accountnamen
Die Optionen accountDomainName and accountDomainNameShort
werden für zwei Zwecke genutzt: Erstens bieten sie Mehrdomain-Authentifizierung und
Möglichkeiten zur Ausfallsicherung, und zweitens werden sie benutzt, um
Benutzernamen zu normalisieren, nach der Vorgabe der Option
accountCanonicalForm. Diese Option kann einen der folgenden Werte
annehmen:
Die standardmäßige Normalisierung hängt davon am, welche Optionen zum Account-DN
übergeben wurden. Wenn accountDomainNameShort angegeben wurde, ist
der Standardwert von accountCanonicalFormACCTNAME_FORM_BACKSLASH. Wenn dagegen accountDomainName
angegeben wurde, ist der Standardwert ACCTNAME_FORM_PRINCIPAL.
Die Normalisierung von Account-Namen stellt sicher, dass der String, der zur
Identifizierung eines Accounts verwendet wird, einheitlich ist, egal was
an bind() übergeben wurde. Wenn der Benutzer bspw.
abaker@example.com oder einfach abaker
als Benutzernamen angibt und accountCanonicalForm auf 3 gesetzt ist,
wird der normalisierte Name EXAMPLE\abaker sein.
Authentifizierung auf mehreren Domains und AusfallsicherungZend_Ldap an sich wird nicht versuchen, sich mit mehreren
Servern zu verbinden. Allerdings ist Zend_Ldap auf dieses
Szenario vorbereitet. Dazu können Sie einfach ein Array mit Optionen für mehrere
Server durchlaufen und nacheinander versuchen, sich mit jedem Server zu verbinden.
Wie oben beschrieben wird bind() automatisch jeden Benutzernamen
normalisieren, also ist es egal, ob der Benutzer abaker@foo.net oder
W\bcarter oder cdavis als Benutzernamen angibt -
bind() wird fehlschlagen, wenn der Login nicht erfolgreich war.
Das folgende Beispiel zeigt Authentifizierung auf mehreren Domains und eine
Ausfallsicherung.
array(
'host' => 's0.foo.net',
'username' => 'CN=user1,DC=foo,DC=net',
'password' => 'pass1',
'bindRequiresDn' => true,
'accountDomainName' => 'foo.net',
'accountDomainNameShort' => 'FOO',
'accountCanonicalForm' => 4, // ACCT_FORM_PRINCIPAL
'baseDn' => 'OU=Sales,DC=foo,DC=net',
),
'server2' => array(
'host' => 'dc1.w.net',
'useSsl' => true,
'username' => 'user1@w.net',
'password' => 'pass1',
'accountDomainName' => 'w.net',
'accountDomainNameShort' => 'W',
'accountCanonicalForm' => 4, // ACCT_FORM_PRINCIPAL
'baseDn' => 'CN=Users,DC=w,DC=net',
),
);
$ldap = new Zend_Ldap();
foreach ($multiOptions as $name => $options) {
echo "Versuche, mit den Server-Optionen für '$name' zu verbinden\n";
$ldap->setOptions($options);
try {
$ldap->bind($acctname, $password);
$acctname = $ldap->getCanonicalAccountName($acctname);
echo "AUSGEFÜHRT: $acctname angemeldet\n";
return;
} catch (Zend_Ldap_Exception $zle) {
echo ' ' . $zle->getMessage() . "\n";
if ($zle->getCode() === Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH) {
continue;
}
}
}
]]>
Wenn die Bindung an einen Server aus irgendeinem Grund fehlschlägt, wird sie
mit dem nächsten Server erneut versucht.
Der Aufruf von getCanonicalAccountName gibt den normalisierten
Account-Namen zurück, den die Anwendung vermutlich benutzen würde, um Daten - wie
bspw. Einstellungen - damit zu assoziieren. Die Option
accountCanonicalForm = 4, die in diesem Fall in den Optionen aller
Server gesetzt ist, stellt sicher, dass die normalisierte Form in einem
einheitlichen Format ist, egal welcher Server am Ende benutzt wurde.
Die besondere Ausnahme LDAP_X_DOMAIN_MISMATCH tritt auf, wenn ein
Account-Name angegeben wurde, der einen Domain-Teil beinhaltet (bspw.
abaker@foo.net oder FOO\abaker und nicht nur
abaker), aber dieser Domain-Teil mit keiner Domain in den aktuell
ausgewählten Server-Optionen übereinstimmt. Diese Ausnahme zeigt an, dass der
Server keine Autorität für diesen Account ist. In diesem Fall wird eine Bindung
nicht ausgeführt, um unnötige Server-Anfragen zu vermeiden. Beachten Sie, dass
die Anweisung continue in diesem Beispiel keine Auswirkung hat, aber
Sie werden im praktischen Einsatz zur Fehlerbehandlung und aus Debugging-Gründen
wahrscheinlich neben LDAP_X_DOMAIN_MISMATCH auch noch auf die
Exception-Codes LDAP_NO_SUCH_OBJECT und
LDAP_INVALID_CREDENTIALS prüfen wollen.
Der obige Code ist dem sehr ähnlich, der in Zend_Auth_Adapter_Ldap
verwendet wird. Wir empfehlen daher, einfach den Authentifizierungs-Adapter
für Multi-Domain-Authentifizierung und LDAP-basierte Authentifizierung mit
Ausfallsicherung zu verwenden (oder kopieren Sie den Code oben).