Bereiche für Administratoren gehören zum Standard bei der Webseitenentwicklung. Ob Blog, Wiki oder Content Management System, letztendlich muss jede Anwendung einen Adminbereich anbieten. Ein Login-Dialog plus die Authentifizierung sind somit Minimum für solche Webseiten. Das folgende Beispiel soll eine Möglichkeit der Authentifizierung verdeutlichen. Folgende Funktionalitäten sollen erreicht werden:
- Authentifizierung gegen die Daten eines Nutzers aus der Datenbank
- Eigener Login-Dialog, unabhängig vom Layout des Frontends
- Speicherung des Zeitpunkts des Logins
- Aufgehübschter Login-Dialog
Die Nutzung von CakePHP 1.3.8 wird hier natürlich voraussgesetzt.
Datenbank vorbereiten
Wir benötigen also auf jeden Fall eine Tabelle in einer Datenbank, die unsere Nutzer verwaltet. Dabei brauchen wir neben den normalen Angaben über den Nutzer ein Login- und Passwortfeld. Das SQL-Statement für diese ‘Users’-Tabelle könnte folgendermaßen aussehen:
CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) NOT NULL auto_increment, `login` varchar(255) collate utf8_unicode_ci NOT NULL, `password` char(40) collate utf8_unicode_ci NOT NULL, `email` varchar(255) collate utf8_unicode_ci NOT NULL, `name` varchar(255) collate utf8_unicode_ci default NULL, `created` datetime NOT NULL, `updated` datetime NOT NULL, `last_login` datetime default NULL, PRIMARY KEY (`id`), ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Damit ist der erste Schritt getan. Die Datenbankverbindung muss natürlich in ‘config/database.php’ korrekt angegeben sein, so dass unsere Anwendung später auch die Tabelle ‘Users’ ansprechen kann. Für den zweiten Schritt müssen wir uns die ‘config/core.php’ Datei etwas näher anschauen.
Den Kern (‘core.php’) anpassen
Um das admin-Routing zu aktivieren, muss in der ‘config/core.php’-Datei eine Zeile auskommentiert werden. Seit CakePHP 1.3 nennt sich das Admin-Routing nur noch Prefix-Routing. Beim Aufruf einer Methode, bei der der definierte Prefix mit einem Unterstrich vorangestellt wird, wird auf den entsprechenden Bereich geroutet. Beispiel:
admin_index() => admin/controllers/index manager_index() => manager/controllers/index
Um diese Funktionalität nun zu aktivieren, muss die Zeile
Configure::write('Routing.prefixes', 'admin');
auskommentiert werden. Für andere Prefixes, muss ‘admin’ durch das gewünschte Prefix ersetzt bzw. kann auch ganz einfach ein weiterer Prefix, durch ein Komma getrennt, hinzugefügt werden. CakePHP erzeugt anschließend im Hintergrund die notwendigen Routen. Das Prefix-Routing ist im Manual auch sehr anschaulich beschrieben.
Damit ist auch der zweite Schritt erledigt. Schauen wir uns also den Controller an…
Controller programmieren
Als nächstes brauchen wir einen UsersController, der unter dem Namen ‘users_controller.php’ im Ordner ‘controllers’ abgelegt wird. Dieser besteht eigentlich nur aus zwei Methoden, der ‘login()’ und der ‘logout()’-Methode. Die ‘login()’-Methode wird aufgerufen, wenn der Nutzer seinen Login-Namen und sein Passwort eingegeben hat (dies aber auch nur, weil die Einstellung der AuthComponent entsprechend gesetzt ist, dazu später mehr bei AppController). In der ‘login()’-Methode wird das Layout festgelegt, der Seitenname gesetzt und die Loginzeit gespeichert. Anschließend wird der Nutzer auf die in der AuthComponent definierte Seite weitergeleitet.
Die ‘logout()’-Methode macht ebenfalls nicht viel außer den Nutzer auf die in der AuthComponent definierte Logoutseite weiterzuleiten. Hier also der UsersController:
class UsersController extends AppController { var $name = 'Users'; function login() { $this->layout = 'login'; $this->set('title_for_layout', 'Login'); if (!(empty($this->data)) && $this->Auth->user()) { $this->User->id = $this->Auth->user('id'); $this->User->saveField('last_login', date("Y-m-d H:i:s")); $this->redirect($this->Auth->redirect()); } } function admin_logout() { $this->redirect($this->Auth->logout()); } function admin_index() { $users = $this->User->find('all'); $this->set(compact('users')); } }
Schauen wir uns nun den schon viel besprochenen AppController an.
Authentisierungseinstellungen im AppController einrichten
Im AppController (Name: ‘app_controller.php’ abzulegen in ‘app’) fügen wir die AuthComponente für alle unsere Controller hinzu. Gleichzeitig legen wir bestimmte Eigenschaften fest, wie z.B. das zu nutzende Model (hier ‘User’), die beim Login zu überprüfenden Felder in der Datenbank (Standard sind ‘username’ und ‘password’ – im Beispiel geändert auf ‘login’ und ‘password’), die Login-Method, die Login- und Logout-Weiterleitung, zwei Error-Nachrichten und dass die automatische Weiterleitung deaktiviert wird (‘autoRedirect’ => false: Das ist der Grund, wieso die ‘login()’-Methode im ‘UsersController’ überhaupt erst durchgeführt wird. Diese Einstellungen gelten nun anwendungsweit.
class AppController extends Controller { var $helpers = array('Html', 'Session', 'Form'); var $components = array('Auth' => array( 'userModel' => 'User', 'fields' => array('username' => 'login', 'password' => 'password'), 'loginAction' => array('controller' => 'users', 'action' => 'login', 'admin' => false, 'plugin' => null), 'logoutRedirect' => array('controller' => 'pages', 'action' => 'home', 'admin' => false), 'loginRedirect' => array('controller' => 'Users', 'action' => 'index', 'admin' => true), 'loginError' => 'Fehlerhafte Login-Daten!', 'authError' => 'Bitte geben Sie Ihre gültigen Zugangsdaten ein!', 'autoRedirect' => false ));
function beforeFilter() { if(isset($this->Auth)) { if(isset($this->params['admin']) && $this->params['admin'] == 1) { $this->Auth->allow('login'); #nicht unbedingt nötig } else { $this->Auth->allow('*'); } }
Es fällt auf, dass wir in der ‘beforeFilter()’-Methode noch etwas wichtiges tun. Die ‘beforeFilter()’-Methode wird immer vor der Ausführung einer jeden Action aufgerufen. Daher können wir hier die Abfrage durchführen, ob es sich um einen Aufruf einer geschützten ‘admin_’-Methode handelt oder nicht. Alle ‘admin_’-Methoden sollen ja schließlich nicht unauthorisiert erreichbar sein. Sofern keine ‘admin_()’-Methode aufgerufen wird, sind alle Actions erlaubt.
Ausgabe für den Nutzer – Views
Die Anwendungslogik steht, nun muss der Login-Dialog dem Nutzer noch angezeigt werden. Dafür benötigen wir zwei Views, die unter ‘views/users/’ abgelegt werden müssen. Der Login-Dialog ansich wird in der View ‘login.ctp’ gestaltet. Die View könnte also folgendermaßen aussehen:
<div id="login"> <p id="gohome"> <?php echo $html->link("Zurück zur Webseite", '/'); ?> </p> <h1>Bitte melden Sie sich an</h1> <?php echo $form->create('User'); echo $form->input('login', array('between' => '<br />')); echo $form->input('password', array( 'between' => '<br />', 'label' => 'Passwort')); ?> <?php # Auth error message if ($session->check('Message.auth')) { echo $this->Session->flash('auth'); } echo $form->submit('einloggen', array( 'class' => 'button-primary')); echo $form->end(); ?> </div>
Hier passiert eigentlich nichts weltbewegendes. Mit Hilfe des FormHelpers wird der Login-Dialog gestaltet, d.h. Login- und Passwort-Feld generiert. Anschließend wird noch ein SubmitButton erzeugt. Falls die Zugangsdaten nicht stimmen sollten, wird mit Hilfe der AuthError-Nachricht die Fehlermeldung (die wir im AppController definiert haben) angezeigt. D. e View steht, sie sieht jedoch noch sehr karg aus. CSS schafft Abhilfe im nächsten Schritt.
Um feststellen zu können, dass der Login funktioniert, brauchen wir noch die ‘admin_index.ctp’-Seite. Hier halten wir es einfach und lassen einfach ‘Hello World’ ausgeben. Die ‘admin_index.ctp’ muss ebenfalls im ‘views/users/’-Ordner abgelegt werden. Soviel zu den Views…
Alles schön übersichtlich – Layout
In der ‘login()’-Methode wurde das Layout für diese Action gesetzt; es wird mit ‘login’ angesprochen. Also müssen wir noch ein Layout ‘login.ctp’ innerhalb von ‘views/layouts’ erstellen. Dies kann so aussehen:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="de-DE"> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title><?php echo $title_for_layout; ?></title> <?php echo $html->css('admin_login'); ?> </head> <body> <?php $session->flash(); echo $content_for_layout; ?> </body> </html>
Wichtig ist hier eigentlich nur, dass die $content_for_layout Variable eingebunden ist, um unsere erstellte ‘login.ctp’-View auch einzubetten. Damit das ganz noch schön wird, verweisen wir auf eine CSS-Datei; wir nennen sie ‘admin_login.css’. Wie die aussehen kann, kommt nun…
Aufhübschen – CSS
Der letzte Schritt ist vielleicht der aufwändigste, denn es geht um das “Schön machen” des Login-Dialogs. Dabei hat jeder natürlich seine eigenen Vorstellungen. Der Vollständigkeit halber daher hier ein mögliches CSS, welches den Login-Dialog einigermaßen ansprechend gestaltet. Um im Beispiel zu bleiben, muss das CSS als ‘admin_login.css’ in ‘webroot/css’ abgelegt werden, denn darauf haben wir schließlich in unserem Layout verwiesen.
@CHARSET "UTF-8"; * { margin:0; padding:0; } body { font:11px "Lucida Grande",Verdana,Arial, "Bitstream Vera Sans",sans-serif; background: #fff; } #login { margin:7em auto; width:320px; } form { -moz-box-shadow:0 4px 18px #C8C8C8; background:-moz-linear-gradient(top , #b9d5ff, #f0f6ff); border:1px solid #E5E5E5; font-weight:normal; padding:16px 16px 40px; margin: 0 auto; } h1{ display:block; overflow:hidden; margin:0 0 1em 1em; color: #ccc; } label { color:#777777; font-size:13px; } .button-primary { border:1px solid; cursor:pointer; font-family:"Lucida Grande",Verdana,Arial, "Bitstream Vera Sans",sans-serif; font-size:12px; margin-right: 0em; padding:3px 10px; text-decoration:none; float:right; } #gohome a { position:absolute; left: 15px; top: 15px; text-decoration:none; color: #333; background: none repeat scroll 0 0 #E3E3E3; } #authMessage, .message { -moz-border-radius:3px 3px 3px 3px; border-style:solid; border-width:1px; padding:12px; margin: 0.5em 0 1em 0; background-color:#FFEBE8; border-color:#CC0000; } #UserPassword, #UserLogin { background:none repeat scroll 0 0 #FBFBFB; border:1px solid #E5E5E5; font-size:24px; margin-bottom:16px; margin-right:6px; margin-top:2px; padding:3px; width:97%; } input { color:#555555; margin-right: 0.5em; }
Nun geht’s ans Ausprobieren!
Hallo, ich bin Cake Anfänger… Ich habe diese kleine Tut hier 1:1 nach gebaut, aber bei mir funktioniert es nicht so wie ich es gern hätte. Wie kann ich z.b. in einem view dann prüfen ob der “admin” eingeloggt ist, und nur wenn das der fall ist möchte ich z.B. andere links anzeigen wie für die normalen user
Hallo Maik, darüber habe ich hier (http://www.ooyoo.de/wordpress/?p=103) bereits etwas geschrieben. Ich hoffe, das hilft Dir weiter.