<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 16652 -->
<!-- Reviewed: no -->
<sect1 id="zend.auth.introduction">

    <title>Einführung</title>

    <para>
        <classname>Zend_Auth</classname> bietet eine <acronym>API</acronym> für das Authentifizieren
        und enthält konkrete Authentifizierungs-Adapter für übliche Use Case Szenarien.
    </para>

    <para>
        <classname>Zend_Auth</classname> behandelt nur die
        <emphasis>Authentifizierung</emphasis> und nicht die
        <emphasis>Authorisierung</emphasis>. Authentifizierung ist lose definiert als
        das Ermitteln ob eine Entität aktuell das ist was Sie vorgibt zu sein (z.B.
        Identifizierung), basierend auf einem Set von Zeugnissen. 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
        <classname>Zend_Auth</classname>. Für weitere Informationen über Authorisierung und
        Zugriffskontrolle mit dem Zend Framework, sollte <link
            linkend="zend.acl"><classname>Zend_Acl</classname></link> angeschaut werden.
    </para>

    <note>
        <para>
            Die <classname>Zend_Auth</classname> Klasse implementiert das Singleton Pattern - nur
            eine Instanz der Klasse ist vorhanden - durch Ihre statische
            <methodname>getInstance()</methodname> Methode. Das bedeutet das die Verwendung des
            <emphasis>new</emphasis> Operators und des <emphasis>clone</emphasis> Keywords mit der
            <classname>Zend_Auth</classname> Klasse nicht funktioniert; stattdessen muß
            <methodname>Zend_Auth::getInstance()</methodname> verwendet werden.
        </para>
    </note>

    <sect2 id="zend.auth.introduction.adapters">

        <title>Adapter</title>

        <para>
            Ein <classname>Zend_Auth</classname> Adapter wird verwendet um sich gegenüber einem
            speziellen Typ von Authentifizierungs Services zu authentifizieren, wie
            <acronym>LDAP</acronym>, <acronym>RDBMS</acronym>, oder Datei-basierenden Speichern.
            Verschiedene Adapter besitzen leicht unterschiedliche Optionen und Verhaltensweisen,
            aber einige grundlegende Dinge sind für Authentifizierungs Adapter üblich. Zum Beispiel
            das die Authentifizierung Zeugnisse akzeptiert werden (enthält auch vorgegebene
            Identitäten), das Abfragen am Authentifizierungsservice durchgeführt werden, und das
            Ergebnisse zurückgegeben werden, sind für <classname>Zend_Auth</classname> Adapter
            üblich.
        </para>

        <para>
            Jede <classname>Zend_Auth</classname> Adapter Klasse implementiert
            <classname>Zend_Auth_Adapter_Interface</classname>. Dieses Interface definiert eine
            Methode, <methodname>authenticate()</methodname>, die eine Adapter Klasse
            implementieren muß um eine Authentifizierungsanfrage auszuführen. Jede Adapter Klasse
            muß vorher vorbereitet sein bevor <methodname>authenticate()</methodname> aufgerufen
            wird. Diese Vorbereitung des Adapters enthält das Setzen der Zeugnisse (z.B.
            Benutzername und Passwort) und die Definition von Werten für Adapter spezifische
            Konfigurationoptionen, wie Datenbank Verbindungsdaten für einen Datenbank Tabellen
            Adapter.
        </para>

        <para>
            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:
        </para>

        <programlisting language="php"><![CDATA[
class MyAuthAdapter implements Zend_Auth_Adapter_Interface
{
    /**
     * Setzt Benutzername und Passwort für die Authentifizierung
     *
     * @return void
     */
    public function __construct($username, $password)
    {
        // ...
    }

    /**
     * Führt einen Authentifizierungs-Versuch durch
     *
     * @throws Zend_Auth_Adapter_Exception Wenn die Authentifizierung nicht
     *                                     durchgeführt wurde
     * @return Zend_Auth_Result
     */
    public function authenticate()
    {
        // ...
    }
}
]]></programlisting>

        <para>
            Wie im Docblock angegeben, muß <methodname>authenticate()</methodname> eine Instanz von
            <classname>Zend_Auth_Result</classname> (oder einer von
            <classname>Zend_Auth_Result</classname> abgeleiteten Klassen) zurückgeben. Wenn aus
            bestimmten Gründen eine Durchführung einer Authentifizierungs-Anfrage nicht möglich
            ist, sollte <methodname>authenticate()</methodname> eine Ausnahme werfen die von
            <classname>Zend_Auth_Adapter_Exception</classname> abgeleitet ist.
        </para>

    </sect2>

    <sect2 id="zend.auth.introduction.results">

        <title>Ergebnisse</title>

        <para>
            <classname>Zend_Auth</classname> Adapter geben eine Instanz von
            <classname>Zend_Auth_Result</classname> mit Hilfe von
            <methodname>authenticate()</methodname> zurück um die Ergebnisse des
            Authentifizierungs-Versuches darzustellen. Adapter veröffentlichen das
            <classname>Zend_Auth_Result</classname> Objekt bei der Erstellung, so das die folgenden
            vier Methoden ein grundsätzliches Set von Benutzerbezogenen Operationen bieten die für
            die Ergebnisse von <classname>Zend_Auth</classname> Adapter üblich sind:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <methodname>isValid()</methodname> - Gibt <constant>TRUE</constant> zurück wenn
                    und nur wenn das Ergebnis einen erfolgreichen Authentifizierungs-Versuch
                    repräsentiert
                </para>
            </listitem>
            <listitem>
                <para>
                    <methodname>getCode()</methodname> - Gibt einen konstanten
                    <classname>Zend_Auth_Result</classname> Identifizierer damit der Typ des
                    Authentifizierungs-Fehlers, 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 Authentifizierungs-Ergebnisse zu erhalten.
                    Eine andere Verwendung dieses Features ist es spezielle, benutzerdefinierte
                    Nachrichten anzubieten, um Benutzern eine bessere Usability zu ermöglichen,
                    einfach dadurch das Entwickler dazu aufgerufen sind die Risiken solche
                    defailierte Informationen Benutzern anzubieten, statt einer generellen
                    Nachricht eines Authentifizierungs-Fehlers. Für weitere Informationen siehe
                    die Notiz anbei.
                </para>
            </listitem>
            <listitem>
                <para>
                    <methodname>getIdentity()</methodname> - Gibt die Identität des
                    Authentifizierungs-Versuchs zurück
                </para>
            </listitem>
            <listitem>
                <para>
                    <methodname>getMessages()</methodname> - Gibt ein Array von Nachrichten
                    zurück nach einem fehlgeschlagenen Authentifizierungs-Versuch
                </para>
            </listitem>
        </itemizedlist>

        <para>
            Ein Entwickler kann wünschen basierend auf dem Typ des Authentifizierungs-Ergebnisses zu
            verzweigen um spezialisiertere Operationen durchzuführen. 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 Authentifizierungs-Ergebnisse an den Benutzer. Die
            folgenden Ergebniscodes sind vorhanden:
        </para>

        <programlisting language="php"><![CDATA[
Zend_Auth_Result::SUCCESS
Zend_Auth_Result::FAILURE
Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND
Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS
Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID
Zend_Auth_Result::FAILURE_UNCATEGORIZED
]]></programlisting>

        <para>
            Das folgende Beispiel zeigt wie ein Entwickler anhand des Ergebniscodes verzweigen
            könnte:
        </para>

        <programlisting language="php"><![CDATA[
// Innerhalb von AuthController / loginAction
$result = $this->_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 Zeugnissen machen **/
        break;

    case Zend_Auth_Result::SUCCESS:
        /** Was wegen erfolgreicher Authentifizierung machen **/
        break;

    default:
        /** Was wegen anderen Fehlern machen **/
        break;
}
]]></programlisting>

    </sect2>

    <sect2 id="zend.auth.introduction.persistence">

        <title>Dauerhafte Identitäten</title>

        <para>
            Eine Anfrage zu authentifizieren die Authentifizierungs Zeugnisse enthält ist per se
            nützlich, aber auch wichtig um die Authentifizierungs Identität bearbeiten zu können
            ohne das immer die Authentifizierungs Zeugnisse mit jeder Anfrage vorhanden sein müssen.
        </para>

        <para>
            Trotzdem ist <acronym>HTTP</acronym> ein statusloses Protokoll, und Techniken wie
            Cookies und Sessions wurden entwickelt um Stati über mehrere Anfragen hinweg in
            Server-seitigen Web Anwendungen zu erhalten.
        </para>

        <sect3 id="zend.auth.introduction.persistence.default">

            <title>Normale Persistenz in PHP Sessions</title>

            <para>
                 Standardmäßig bietet <classname>Zend_Auth</classname> dauerhafte Speicherung der
                 Identität eines erfolgreichen Authentifizierungs Versuches durch Verwendung der
                 <acronym>PHP</acronym> Session. Bei einem erfolgreichen Authentifizierungs Versuch
                 speichert <methodname>Zend_Auth::authenticate()</methodname> die Identität des
                 Authentifizierungs Ergebnisses im persistenten Speicher. Solange die Konfiguration
                 nicht verändert wird, verwendet <classname>Zend_Auth</classname> eine
                 Speicherklasse die <classname>Zend_Auth_Storage_Session</classname> heißt und die
                 im Gegenzug <link linkend="zend.session"><classname>Zend_Session</classname></link>
                 verwendet. Eine eigene Klasse kann stattdessen verwendet werden, indem ein Objekt
                 an <methodname>Zend_Auth::setStorage()</methodname> übergeben wird welches
                 <classname>Zend_Auth_Storage_Interface</classname> implementiert.
            </para>

            <note>
                <para>
                    Wenn das automatische persistente Speichern der Identität für einen bestimmten
                    Anwendungsfall nicht anwendbar ist, können Entwickler trotzdem die
                    <classname>Zend_Auth</classname> Klasse weiterhin verwenden statt direkt eine
                    Adapterklasse anzusprechen.
                </para>
            </note>

            <example id="zend.auth.introduction.persistence.default.example">

                <title>Den Namensraum der Session ändern</title>

                <para>
                    <classname>Zend_Auth_Storage_Session</classname> verwendet einen Session
                    Namensraum von '<classname>Zend_Auth</classname>'. Diese Namensraum kann
                    überschrieben werden indem ein anderer Wert an den Konstruktor von
                    <classname>Zend_Auth_Storage_Session</classname> übergeben wird, und dieser Wert
                    wird intern an den Konstruktor von <classname>Zend_Session_Namespace</classname>
                    weitergereicht. Das sollte vor einem Versuch einer Authentifizierung stattfinden
                    da <methodname>Zend_Auth::authenticate()</methodname> die automatische
                    Speicherung der Identität durchführt.
                </para>

                <programlisting language="php"><![CDATA[
// Eine Referenz zur Singleton Instanz von Zend_Auth speichern
$auth = Zend_Auth::getInstance();

// 'someNamespace' statt 'Zend_Auth' verwenden
$auth->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);
]]></programlisting>

            </example>

        </sect3>

        <sect3 id="zend.auth.introduction.persistence.custom">

            <title>Eigene Speicher implementieren</title>

            <para>
                Zeitweise wollen Entwickler einen anderen Speichermechanismus für Identitäten
                verwenden als es von <classname>Zend_Auth_Storage_Session</classname> angeboten
                wird. Für solche Fälle können Entwickler einfach
                <classname>Zend_Auth_Storage_Interface</classname> implementieren und eine Instanz
                der Klasse an <methodname>Zend_Auth::setStorage()</methodname> übergeben.
            </para>

            <example id="zend.auth.introduction.persistence.custom.example">

                <title>Eine eigene Speicher Klasse verwenden</title>

                <para>
                    Um eine andere Speicherklasse für die Persistenz von Identitäten zu verwenden
                    als sie durch <classname>Zend_Auth_Storage_Session</classname> angeboten wird,
                    können Entwickler <classname>Zend_Auth_Storage_Interface</classname>
                    implementieren:
                </para>

                <programlisting language="php"><![CDATA[
class MyStorage implements Zend_Auth_Storage_Interface
{
    /**
     * Gibt true zurück wenn und nur wenn der Speicher leer ist
     *
     * @throws Zend_Auth_Storage_Exception Wenn es unmöglich ist festzustellen
     *                                     ob der Speicher leer ist
     * @return boolean
     */
    public function isEmpty()
    {
        /**
         * @todo Implementierung
         */
    }

    /**
     * Gibt den Inhalt des Speichers zurück
     *
     * Das Verhalten ist undefiniert wenn der Speicher leer ist.
     *
     * @throws Zend_Auth_Storage_Exception Wenn das Lesen von Lesen vom Speicher
     *                                     unmöglich ist
     * @return mixed
     */
    public function read()
    {
        /**
         * @todo Implementierung
         */
    }

    /**
     * Schreibt $contents in den Speicher
     *
     * @param  mixed $contents
     * @throws Zend_Auth_Storage_Exception Wenn das Schreiben von $contents in
     *                                     den Speicher unmöglich ist
     * @return void
     */
    public function write($contents)
    {
        /**
         * @todo Implementierung
         */
    }

    /**
     * Löscht die Intalte vom Speicher
     *
     * @throws Zend_Auth_Storage_Exception Wenn das Löschen der Inhalte vom
     *                                     Speicher unmöglich ist
     * @return void
     */
    public function clear()
    {
        /**
         * @todo Implementierung
         */
    }

}
]]></programlisting>

                <para>
                    Um diese selbstgeschriebene Speicherklasse zu verwenden wird
                    <methodname>Zend_Auth::setStorage()</methodname> aufgerufen bevor eine
                    Authentifizierungsanfrage stattfindet:
                </para>

                <programlisting language="php"><![CDATA[
// Zend_Auth anweisen das die selbstdefinierte Speicherklasse verwendet wird
Zend_Auth::getInstance()->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);
]]></programlisting>

            </example>

        </sect3>

    </sect2>

    <sect2 id="zend.auth.introduction.using">

        <title>Verwendung</title>

        <para>
            Es gibt zwei vorhandene Wege um <classname>Zend_Auth</classname> Adapter zu verwenden:
        </para>

        <orderedlist>
            <listitem>
                <para>
                    Indirekt durch <methodname>Zend_Auth::authenticate()</methodname>
                </para>
            </listitem>
            <listitem>
                <para>
                    Direkt durch die <methodname>authenticate()</methodname> Methode des Adapters
                </para>
            </listitem>
        </orderedlist>

        <para>
            Das folgende Beispiel zeigt wie ein <classname>Zend_Auth</classname> Adapter indirekt
            verwendet werden kann, durch die Verwendung der <classname>Zend_Auth</classname> Klasse:
        </para>

        <programlisting language="php"><![CDATA[
// Eine Referenz zur Singleton-Instanz von Zend_Auth erhalten
$auth = Zend_Auth::getInstance();

// Authentifizierungs Adapter erstellen
$authAdapter = new MyAuthAdapter($username, $password);

// Authentifizierungs Versuch, das Ergebnis abspeichern
$result = $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
}
]]></programlisting>

        <para>
            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:
        </para>

        <programlisting language="php"><![CDATA[
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
    // Identität existiert; auslesen
    $identity = $auth->getIdentity();
}
]]></programlisting>

        <para>
            Um eine Identität vom persistenten Speicher zu entfernen muß einfach die
            <methodname>clearIdentity()</methodname> Methode verwendet werden. Das würde
            typischerweise für die Implementierung einer "Abmelde" Operation in einer
            Anwendung Verwendung finden.
        </para>

        <programlisting language="php"><![CDATA[
Zend_Auth::getInstance()->clearIdentity();
]]></programlisting>

        <para>
            Wenn die automatische Verwendung von persistenten Speichern für einen bestimmten
            Verwendungszweck unangebracht ist, kann ein Entwickler einfach die Verwendung der
            <classname>Zend_Auth</classname> Klasse umgehen, und eine Adapter Klasse direkt
            verwenden. Die direkte Verwendung einer Adapterklasse enthält das Konfigurieren und
            Vorbereiten eines Adapter Objektes und den Aufruf dessen
            <methodname>authenticate()</methodname> Methode. Adapter-spezifische Details werden in
            der Dokumentation jeden Adapters besprochen. Das folgende Beispeil verwendet
            <classname>MyAuthAdapter</classname> direkt:
        </para>

        <programlisting language="php"><![CDATA[
// Den Authentifizierungs Adapter erstellen
$authAdapter = new MyAuthAdapter($username, $password);

// Authentifizierungs Versuch, speichere das Ergebnis
$result = $authAdapter->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
}
]]></programlisting>

    </sect2>

</sect1>
<!--
vim:se ts=4 sw=4 et:
-->