EinführungZend_Auth bietet eine API für das Authentifizieren
und enthält konkrete Authentifizierungs-Adapter für übliche Use-Case-Szenarien.
Zend_Auth behandelt nur die
Authentifizierung und nicht die
Authorisierung. Authentifizierung ist frei definiert als
das Ermitteln, ob eine Entität aktuell das ist, was sie vorgibt zu sein (z.B.
Identifizierung), basierend auf einem Set von Anmeldedaten. Authorisierung, der Prozess des
Entscheidens, ob es einer Entität erlaubt wird, auf andere Entitäten Zugriff zu erhalten,
oder um auf diesen Operationen durchzuführen, ist ausserhalb der Möglichkeit von
Zend_Auth. Für weitere Informationen über Authorisierung und
Zugriffskontrolle mit dem Zend Framework, sollte Zend_Acl angeschaut werden.
Die Zend_Auth Klasse implementiert das Singleton Pattern - nur
eine Instanz der Klasse ist vorhanden - durch ihre statische
Methode getInstance(). Das bedeutet, dass die Verwendung des
Operators new und des Schlüsselworts clone mit der
Klasse Zend_Auth nicht funktioniert; stattdessen muß
Zend_Auth::getInstance() verwendet werden.
Adapter
Ein Zend_Auth-Adapter wird verwendet, um sich gegenüber einem
speziellen Typ von Authentifizierungsdiensten zu authentifizieren, wie
LDAP, RDBMS, oder dateibasierenden Speichern.
Verschiedene Adapter besitzen leicht unterschiedliche Optionen und Verhaltensweisen,
aber einige grundlegende Dinge haben Authentifizierungsadapter gemeinsam. Zum Beispiel
dass für die Authentifizierung Anmeldedaten akzeptiert werden (enthält auch vorgegebene
Identitäten), dass Abfragen am Authentifizierungsservice durchgeführt werden, und dass
Ergebnisse zurückgegeben werden, sind für Zend_Auth-Adapter
gebräuchlich.
Jede Zend_Auth-Adapterklasse implementiert
Zend_Auth_Adapter_Interface. Dieses Interface definiert eine
Methode authenticate(), die eine Adapterklasse
implementieren muß, um eine Authentifizierungsanfrage auszuführen. Jede Adapterklasse
muß vorher vorbereitet werden, bevor authenticate() aufgerufen
wird. Diese Vorbereitung des Adapters enthält das Setzen der Anmeldedaten (z.B.
Benutzername und Passwort) und die Definition von Werten für adapterspezifische
Konfigurationoptionen, wie Datenbankverbindungsdaten für einen Datenbank-Tabellen-Adapter.
Das folgende ist ein Beispiel eines Authentifierungs-Adapters der einen Benutzernamen
und ein Passwort für die Authentifizierung benötigt. Andere Details, wie zum Beispiel
der Authentifizierungs-Service abgefragt wird, werden der Kürze halber ausgelassen:
Wie im Docblock angegeben, muß authenticate() eine Instanz von
Zend_Auth_Result (oder einer von
Zend_Auth_Result abgeleiteten Klassen) zurückgeben. Wenn aus
bestimmten Gründen eine Durchführung einer Authentifizierungsanfrage nicht möglich
ist, sollte authenticate() eine Ausnahme werfen, die von
Zend_Auth_Adapter_Exception abgeleitet ist.
ErgebnisseZend_Auth-Adapter geben eine Instanz von
Zend_Auth_Result mit Hilfe von
authenticate() zurück, um die Ergebnisse des
Authentifizierungsversuchs darzustellen. Adapter befüllen das
Objekt Zend_Auth_Result bei der Erstellung, so dass die folgenden
vier Methoden ein grundsätzliches Set von benutzerbezogenen Operationen bieten, die für
die Ergebnisse von Zend_Auth Adapter üblich sind:
isValid() - Gibt TRUE zurück, wenn
und nur wenn das Ergebnis einen erfolgreichen Authentifizierungsversuch
repräsentiert.
getCode() - Gibt einen konstanten
Zend_Auth_Result-Identifizierer zurück, damit der Typ des
Authentifizierungsfehlers, oder des Erfolgs der stattgefunden hat,
ermittelt werden kann. Das kann in Situationen verwendet werden, in denen der
Entwickler die verschiedenen Ergebnistypen der Authentifizierung
unterschiedlich behandeln will. Das erlaubt es dem Entwickler zum Beispiel
detailierte Statistiken über die Authentifizierungsergebnisse zu erhalten.
Eine andere Verwendung dieses Features ist es spezielle, benutzerdefinierte
Nachrichten anzubieten, um Benutzern eine bessere Usability zu ermöglichen,
einfach dadurch dass Entwickler dazu aufgerufen sind, die Risiken solche
detaillierte Informationen Benutzern anzubieten, statt einer generellen
Nachricht eines Authentifizierungsfehlers. Für weitere Informationen siehe
die Notiz anbei.
getIdentity() - Gibt die Identität des
Authentifizierungsversuchs zurück
getMessages() - Gibt ein Array von Nachrichten
zurück nach einem fehlgeschlagenen Authentifizierungsversuch
Ein Entwickler möchte basierend auf dem Typ des Authentifizierungsergebnisses zu
spezialisierteren Operationen verzweigen. Einige Operationen die für
Entwickler nützlich sein können, sind zum Beispiel das Sperren von Konten nachdem zu oft
ein falsches Passwort angegeben wurde, das Markieren von IP-Adressen, nachdem zuviele
nicht existierende Identitäten angegeben wurden und das Anbieten von speziellen,
benutzerdefinierten Nachrichten für Authentifizierungsergebnisse an den Benutzer. Die
folgenden Ergebniscodes sind vorhanden:
Das folgende Beispiel zeigt, wie ein Entwickler anhand des Ergebniscodes verzweigen
könnte:
_auth->authenticate($adapter);
switch ($result->getCode()) {
case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
/** Was wegen nicht existierender Identität machen **/
break;
case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
/** Was wegen ungültigen Anmeldededaten machen **/
break;
case Zend_Auth_Result::SUCCESS:
/** Was wegen erfolgreicher Authentifizierung machen **/
break;
default:
/** Was wegen anderen Fehlern machen **/
break;
}
]]>Dauerhafte Identitäten
Eine Anfrage zu authentifizieren, die Anmeldedaten enthält ist per se
nützlich, aber auch wichtig, um die Authentifizierungs-Identität bearbeiten zu können,
ohne dass immer die Anmeldedaten bei jeder Anfrage vorhanden sein müssen.
Trotzdem ist HTTP ein statusloses Protokoll, und Techniken wie
Cookies und Sessions wurden entwickelt um Stati über mehrere Anfragen hinweg in
server-seitigen Web-Anwendungen zu erhalten.
Normale Persistenz in PHP-Sessions
Standardmäßig bietet Zend_Auth dauerhafte Speicherung der
Identität eines erfolgreichen Authentifizierungsversuches durch Verwendung der
PHP-Session. Bei einem erfolgreichen Authentifizierungsversuch
speichert Zend_Auth::authenticate() die Identität des
Authentifizierungsergebnisses im persistenten Speicher. Solange die Konfiguration
nicht verändert wird, verwendet Zend_Auth eine
Speicherklasse die Zend_Auth_Storage_Session heißt und die
im Gegenzug Zend_Session
verwendet. Eine eigene Klasse kann stattdessen verwendet werden, indem ein Objekt
an Zend_Auth::setStorage() übergeben wird, welches
Zend_Auth_Storage_Interface implementiert.
Wenn das automatische persistente Speichern der Identität für einen bestimmten
Anwendungsfall nicht anwendbar ist, können Entwickler trotzdem die
Zend_Auth Klasse weiterhin verwenden, statt direkt eine
Adapterklasse anzusprechen.
Den Namensraum der Session ändernZend_Auth_Storage_Session verwendet einen Session
Namensraum von 'Zend_Auth'. Dieser Namensraum kann
überschrieben werden, indem ein anderer Wert an den Konstruktor von
Zend_Auth_Storage_Session übergeben wird, und dieser Wert
wird intern an den Konstruktor von Zend_Session_Namespace
weitergereicht. Das sollte vor einem Versuch einer Authentifizierung stattfinden,
da Zend_Auth::authenticate() die automatische
Speicherung der Identität durchführt.
setStorage(new Zend_Auth_Storage_Session('someNamespace'));
/**
* @todo Den Auth Adapter $authAdapter erstellen
*/
// Authentifizieren, das Ergebnis speichern, und die Identität bei Erfolg
// persistent machen
$result = $auth->authenticate($authAdapter);
]]>Eigene Speicher implementieren
Zeitweise wollen Entwickler einen anderen Speichermechanismus für Identitäten
verwenden als es von Zend_Auth_Storage_Session angeboten
wird. Für solche Fälle können Entwickler einfach
Zend_Auth_Storage_Interface implementieren und eine Instanz
der Klasse an Zend_Auth::setStorage() übergeben.
Eine eigene Speicherklasse verwenden
Um eine andere Speicherklasse für die Persistenz von Identitäten zu verwenden
als sie durch Zend_Auth_Storage_Session angeboten wird,
können Entwickler Zend_Auth_Storage_Interface
implementieren:
Um diese selbstgeschriebene Speicherklasse zu verwenden wird,
Zend_Auth::setStorage() aufgerufen, bevor eine
Authentifizierungsanfrage stattfindet:
setStorage(new MyStorage());
/**
* @todo Den Auth Adapter $authAdapter erstellen
*/
// Authentifizieren, das Ergebnis speichern, und die Identität bei Erfolg
$result = Zend_Auth::getInstance()->authenticate($authAdapter);
]]>Verwendung
Es gibt zwei vorhandene Wege um Zend_Auth-Adapter zu verwenden:
Indirekt durch Zend_Auth::authenticate()
Direkt durch die authenticate() Methode des Adapters
Das folgende Beispiel zeigt, wie ein Zend_Auth-Adapter indirekt
verwendet werden kann, durch die Verwendung der Klasse Zend_Auth:
authenticate($authAdapter);
if (!$result->isValid()) {
// Authentifizierung fehlgeschlagen; die genauen Gründe ausgeben
foreach ($result->getMessages() as $message) {
echo "$message\n";
}
} else {
// Authentifizierung erfolgreich; die Identität ($username) wird in
// der Session gespeichert
// $result->getIdentity() === $auth->getIdentity()
// $result->getIdentity() === $username
}
]]>
Sobald die Authentifizierung in einer Anfrage durchgeführt wurde, so wie im obigen
Beispiel, ist es sehr einfach zu prüfen, ob eine erfolgreich authentifizierte Identität
existiert:
hasIdentity()) {
// Identität existiert; auslesen
$identity = $auth->getIdentity();
}
]]>
Um eine Identität vom persistenten Speicher zu entfernen, muß einfach die
Methode clearIdentity() verwendet werden. Das würde
typischerweise für die Implementierung einer "Abmelde"-Operation in einer
Anwendung Verwendung finden.
clearIdentity();
]]>
Wenn die automatische Verwendung von persistenten Speichern für einen bestimmten
Verwendungszweck unangebracht ist, kann ein Entwickler einfach die Verwendung der
Klasse Zend_Auth umgehen, und eine Adapterklasse direkt
verwenden. Die direkte Verwendung einer Adapterklasse enthält das Konfigurieren und
Vorbereiten eines Adapter-Objekts und den Aufruf dessen
Methode authenticate(). Adapter-spezifische Details werden in
der Dokumentation jedes Adapters besprochen. Das folgende Beispeil verwendet
MyAuthAdapter direkt:
authenticate();
if (!$result->isValid()) {
// Authentifizierung fehlgeschlagen; die genauen Gründe ausgeben
foreach ($result->getMessages() as $message) {
echo "$message\n";
}
} else {
// Authentifizierung erfolgreich
// $result->getIdentity() === $username
}
]]>