Authentifizierung mit Zend_Auth

0 | 4 Kommentare | 5143 Aufrufe
Sie können diese Wikiseite nach der Anmeldung auf Webmasterpro bearbeiten. Helfen Sie mit und verbessern Sie "Authentifizierung mit Zend_Auth" mit Ihrem Wissen!

Anzeige Hier werben

Die Zend_Auth-Komponente vom Zend Framework bietet einem eine klare Struktur, wie man die Authentifizierung vornhemen kann. Die Komponente bietet HTTP-, Digest-, Datenbank-, LDAP- und eine OpenID-Authenfizierung. Im Ablauf der Authentifizierung unterscheiden sich diese Mechanismen nur in der Initialisierung des Zend_Auth-Objekts.

Für dieses Beispiel nutze ich die Authentifzierung gegen die Daten in einer Datenbank. In der Datenbank sind der Benutzername und das Passwort gespeichert. Das Passwort ist MD5 verschlüsselt.

Nun erstmal die grobe Struktur, wie ihr prüfen könnt, ob der aktuelle Besucher eingeloggt ist oder nicht.

Vorraussetzung

Damit ihr die Code-Beispiele genauso testen könnt, wie sie hier beschrieben sind, muss sich das Zend Framework in eurem include_path befinden. Es muss also ein Zend-Verzeichnis im include_path liegen.

Vorbereitung

Die Datenbankstruktur

 
sql
1
2
3
4
5
6
7
CREATE TABLE `example`.`user` (
    `user_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(255) NOT NULL,
    `password` VARCHAR(32) NOT NULL,
    PRIMARY KEY (`user_id`),
    UNIQUE KEY (`username`)
);

Beispieldaten für die Datenbank

 
sql
1
2
INSERT INTO `example`.`user` (`username`, `password`) VALUES
    ('Max Mustermann', MD5('geheim'));

Ist der Besucher eingeloggt?

Code-Beispiel

 
PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

require_once 'Zend/Auth.php';
$auth = Zend_Auth::getInstance();

require_once 'Zend/Auth/Storage/Session.php';
$storage = new Zend_Auth_Storage_Session;

$auth->setStorage($storage);

if ($auth->hasIdentity()) {
    // eingeloggt
} else {
    // nicht eingeloggt
}

?>

Erklärung des Beispiels

Als erstes besorgen wir uns eine Instanz von Zend_Auth. Das geschieht nicht über new Zend_Auth sondern über Zend_Auth::getInstance(), da es sich bei Zend_Auth um einen Singleton handelt. So kann man in der kompletten Anwendung sehr einfach auf das Objekt zurückgreifen.

Danach müssen wir sagen, wo die Informationen, ob ein Benutzer eingeloggt ist oder nicht, abgelegt sind. In diesem Beispiel nutzen wir Zend_Auth_Storage_Session. Die Informationen werden also in einer Session abgelegt. Diese Komponente kümmert sich auch von selbst darum, dass die Session gestartet wird. Ihr müsst euch also nicht selbst darum kümmern.

Nach diesen paar Zeilen könnte ihr nun mit $auth->hasIdentity() prüfen, ob der Benutzer eingeloggt ist, oder nicht. Diese Methode liefert TRUE zurück, wenn der Benutzer eingeloggt ist, FALSE wenn nicht.

Jetzt fehlt aber noch das Login ansich.

Das Login

Code-Beispiel

 
PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php

require_once 'Zend/Auth.php';
$auth = Zend_Auth::getInstance();

require_once 'Zend/Auth/Storage/Session.php';
$storage = new Zend_Auth_Storage_Session;

$auth->setStorage($storage);

require_once 'Zend/Db.php';
$database = Zend_Db::factory('PDO_MYSQL', array(
    'host'     => 'localhost',
    'username' => 'db-username',
    'password' => 'db-password',
    'dbname'   => 'example'
));

require_once 'Zend/Auth/Adapter/DbTable.php';
$adapter = new Zend_Auth_Adapter_DbTable(
    $database,  // Datenbankverbindung
    'user',     // Tabelle in der Datenbank (hier: example.user)
    'username', // Spalte, in der der Benutzername abgelegt ist
    'password', // Spalte, wo das Passwort abgelegt ist
    'MD5(?)'    // Passwort ist MD5 verschlüsselt
);

$adapter->setIdentity('Max Mustermann')->setCredential('geheim');

$result = $auth->authenticate($adapter);
if ($result->isValid())
{
    echo "Erfolgreich eingeloggt.";
    $storage->write($result->getResultRowObject(
        null, 'password'
    ));
}
else
{
    echo "Login fehlgeschlagen:<br />";
    foreach ($result->getMessages() as $message) {
        echo "- {$message}<br />";
    }
}

?>

Erklärung des Beispiels

Zurerst brauchen wir nochmal die Zend_Auth-Komponente, damit bei der Authentifizierung klar ist, wohin, bei Erfolg, die Daten geschrieben werden müssen, dass der Benutzer eingeloggt ist.

Hier wird zuerst, mit Hilfe der Zend_Db-Komponente eine Datenbankverbindung hergestellt. Dazu wird im Hintergrund die MySQL-Abstraktion von PDO genutzt. Bei euch werden die einzelnen Parameter (host, username, password, dbname) an eure Datenbank angepasst werden.

Danach erstellen wir eine Instanz von Zend_Auth_Adapter_DbTable. Damit definieren wir, dass unsere Benutzerdaten in einer Tabelle in der Datenbank liegen. Als ersten Parameter übergeben wir die, zuvor erstellte, Datenbankverbindung. Der zweite Parameter definiert die Tabelle, wo die Benutzerdaten liegen. In diesem Beispiel liegen die Benutzerdaten in der Tabelle "example.user". Die folgenden zwei Parameter definieren die Namen der Spalten wo der Benutzername bzw. das Passwort abgespeichert sind. Der letzte Parameter gibt an, dass unsere Passwörter in der Datenbank MD5 verschlüsselt sind. Das Fragezeichen (?) ist wichtig, da die Zend_Auth_Adapter_DbTable-Komponente einen SQL-Query zusammenstellt, womit die Daten in der Datenbank überprüft werden können. Das Query enthält am Ende password=MD5("geheim"). Das Fragezeichen wird durch das Passwort ersetzt. Aber darum müsst ihr euch nicht kümmern.

Danach setzt ihr per setIdentity() den Benutzernamen, mit setCredential() das Passwort, des Benutzers, der sich soeben versucht einzuloggen. In diesem Beispiel habe ich nun auf ein Login-Formular etc. verzichtet. Ihr müsstet dann $_POST['username'] und $_POST['password'] oder ähnliches nutzen. Das kommt auf eure Anwendung an.

Nun weiss der Adapter, dass sich wer versucht einzuloggen. Also müssen wir die Prüfung starten. Das passiert mit dem Aufruf von $auth->authenticate($adapter). Damit wird in der Datenbank nach einem Benutzer gesucht, der "Max Mustermann" heisst und das Passwort "geheim" hat.

Ob die Suche nach einem passenden Benutzer erfolgreich war, könnt ihr mit $result->isValid() prüfen. Gibt die Methode TRUE zurück, so war die Authenfizierung erfolgreich. Gibt sie jedoch FALSE zurück, so wurde kein passender Benutzer gefunden. Dann könnt ihr mit $result->getMessages() herausfinden woran es gescheitert ist.

War die Authenfizierung erfolgreich, so müssen die Informationen noch in die Session geschrieben werden. Dafür nutzen wir $storage->write($result->getResultRowObject(null, 'password')). Mit dem ersten Parameter, der bei diesem Beispiel NULL ist, können die Spalten definiert werden, welche in die Session geschrieben werden sollen. Mit dem zweiten Parameter kann man definieren, welche Spalten nicht in die Session geschrieben werden sollen. So werden alle Informationen aus der Datenbanktabelle in die Session geschrieben, ausser der die Spalte "password". Das Passwort ist zwar verschlüsselt, aber trotzdem hat das Passwort dort nichts zu suchen.

Erweiterungen

Benutzer können aktiviert bzw. deaktiviert werden

Können Benutzer aktiviert bzw. deaktiviert werden und gibt es dafür in der Datenbanktabelle z.B. eine Spalte (z.B. active), so kann man beim Instanzieren der Zend_Auth_Adapter_DbTable-Komponente eine kleine Anpassung vornehmen, um den Status zu prüfen.

Neue spalte 'active' in der tabelle  
sql
1
2
3
4
5
6
7
8
CREATE TABLE `example`.`user` (
    `user_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(255) NOT NULL,
    `password` VARCHAR(32) NOT NULL,
    `active` TINYINT(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`user_id`),
    UNIQUE KEY (`username`)
);

Habt ihr die Tabelle bereits aus dem Beispiel weiter oben in der Datenbank (ohne active-Spalte), so könnt ihr die Spalte auch nachträglich einfügen.

Spalte 'active' nachträglich einfügen  
sql
1
ALTER TABLE `example`.`user` ADD COLUMN `active` TINYINT(1) NOT NULL DEFAUL '0';

Nun muss auch der Adapter angepasst werden.

Mit active='1' prüfen, dass der Benutzer auch aktiv sein muss  
PHP
1
2
3
4
5
6
7
$adapter = new Zend_Auth_Adapter_DbTable(
    $database,
    'user',
    'username',
    'password',
    'MD5(?) AND active=1'
);

Nun muss der Wert in der "active"-Spalte 1 sein, damit der Benutzer sich einloggen kann.

Verwandte Artikel


Wikiseite bearbeiten

Diese Seite kann von jedem registrierten Benutzer bearbeitet werden. Bisher haben 2 Personen an der Seite "Authentifizierung mit Zend_Auth" mitgewirkt.

Sie haben einen Fehler entdeckt oder möchten etwas ergänzen? Dann können Sie nach der Anmeldung "Authentifizierung mit Zend_Auth" hier bearbeiten.

Mitarbeiter
  • arbeitet bei der Adcloud GmbH als Software Engineer und beschäftigt sich bereits seit dem Jahr 2000 mit der Entwicklung von dynamischen Internetseiten.
  • Student der Biochemie und seit einigen Jahren im Hobby-Entwicklerbereich tätig. Stärken in XHTML/CSS und PHP, alles was mit Grafik zu tun hat, gehört nicht dazu.

Kommentare: Authentifizierung mit Zend_Auth

Neuen Kommentar schreiben
Fehler im Beispiel-Code
Beantworten

Du hast einen Fehler im Beispiel-Code.

In Zeile 34, statt

$storage->write($result->getResultRowObject(null,'password'));

soll

$storage->write($adapter->getResultRowObject(null, 'password'));

stehen.

Zend Framework VERSION = '1.9.7'

zenduser am 09.02.2010 um 11:21
Re: Fehler im Beispiel-Code
Beantworten

Oh, da hast du Recht. Ich kann den Artikel aber nicht bearbeiten. Beim Speichern bekomme ich immer einen Fehler. Ich schreib diesbezüglich mal einen der Admins an.

Danke für den Hinweis ;)

Jan Pieper am 27.02.2010 um 00:30
Sehr schoen!
Beantworten

Gefällt mir sehr gut, dass ich hier mal was zur Anwendung des Zend Frameworks lese, da will ich auch bald mal ran. Kann man die Komponente Zend_Auth auch gegen eine Datei nutzen, etwa eine XML oder Textdatei. Wenn du da das Beispiel erweiterst, oder einfach Nein sagst, oder mir einen Link gibst, wäre ich dir sehr dankbar. Danke schon mal für den bisherigen Artikel.

Jochen Bauer am 28.03.2009 um 14:27
Re: Sehr schoen!
Beantworten

Die Authentifizierung gegen eine Text- oder XML-Datei kenne ich soweit nun nicht, aber du kannst, wie hier beschrieben, deinen eigenen Adapter schreiben (z.B. My_Auth_Adapter_Xml o.ä.), indem du die authenticate()-Methode mit Leben füllst, wie du es brauchst.

Wenn du einen sauberen Ansatz der Implementierung eines solchen Adapters hast, kannst du ihn ja vielleicht als Erweiterung fürs Framework vorschlagen. Sind aber beides Verfahren, die eher performancelastig sind, wenn es viele Benutzer gibt, da immer die komplette Datei gelesen werden müsste.

Jan Pieper am 29.03.2009 um 21:05