Tym artykułem rozpoczynamy kurs omawiający najważniejsze moduły najważniejszego frameworka PHP, czyli Zend Frameworka.
Możliwość logowania się w serwisach internetowych
jest dziś codziennością. Skonstruowanie
samego okienka logowania nie
jest problemem – to często prosty kod HTML. Cała
magia kryje się pod spodem, w kodzie do którego
dane z formularza (zazwyczaj nazwa użytkownika
i hasło) są wysyłane. Problem sprawdzania autentyczności
danego użytkownika można rozwiązać na
bardzo wiele sposobów. Najczęściej sprowadza się
to do napisania własnej biblioteki, dedykowanej
konkretnej stronie. Jednak jeśli opracowujesz nowy
projekt, warto może zastanowić się nad skorzystaniem
dobrodziejstw Zend Frameworka?
W tym artykule zaprezentujemy jeden z jego
modułów – Zend_Auth. Pozwala on na przeprowadzenie
identyfikacji użytkownika. Identyfikacji,
a więc sprawdzenia czy podana przez logującego
się użytkownika para „Nazwa użytkownika – Hasło”
istnieje. Zend_Auth nie mówi nam natomiast czy
dany użytkownik ma prawa dostępu do danej części
serwisu (za to odpowiada moduł Zend_Acl, którym
zajmiemy się w kolejnym odcinku naszej serii).
Zanim zaczniesz
Zanim zaczniesz czytać dalej, zapoznaj się z modułem
Zend_Controller. Aby korzystać z Zend_Auth, nie musisz używać
co prawda innych modułów Zend Frameworka,
jednak będę tutaj korzystał z Zend_Controllera.
Zatem zrozumienie zasady działania tego modułu
znacznie ułatwi Ci zrozumienie przykładów tu
zamieszczonych.
Kod naszego pliku index.php będzie typowy dla
prostej aplikacji bazującej an Zend Frameworku:
Należy też pamiętać o poprawnej zawartości
pliku .htaccess:
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
Nasze okienko
W celach demonstracyjnych, nasze okienko logowania
maksymalnie uprościmy, tak aby nie zaciemniało
istotnego kodu i abyś nie tracił zbędnego czasu na
analizie HTML. Użyjemy więc następującego kodu:
Logowanie
Całość zaprezentowano na rysunku 1. Pozbawiony
wodotrysków, czysty, wręcz goły formularz.
Nam jednak w zupełności wystarczy.
Powyższy kod zapisz w pliku index.phtml w katalogu
widoków kontrolera Login twojej aplikacji
(np. {stala}application/views/scripts/login{/stala}).
Kod obsługujący logowanie umieścimy w kontrolerze
LoginController. W tej chwili ma on postać:
Już w tej chwili do okna z rysunku 1 możesz się
dostać poprzez adres {stala}http://twojadomena/login{/stala}.
Nasza metoda {stala}checkAction(){/stala} kontrolera Login-Controller może więc wyglądać tak:
public function checkAction() {
Zend_Loader::loadClass(\'Zend_Db_Adapter_Pdo_Mysql\');
Zend_Loader::loadClass(\'Zend_Auth\');
Zend_Loader::loadClass(\'Zend_Auth_Adapter_DbTable\');
$objDbAdapter = new Zend_Db_Adapter_Pdo_Mysql(array(\'host\' => \'localhost\', \'username\' => \'root\', \'password\' => \'\', \'dbname\' => \'users\'));
$objAuthAdapter = new Zend_Auth_Adapter_DbTable($objDbAdapter, \'users\', \'username\', \'password\');
$objAuthAdapter->setIdentity($this->_getParam(\'uname\', \'-\'))->setCredential ($this->_getParam(\'password\'));
$objAuth = Zend_Auth::getInstance();
$objResult = $objAuth->authenticate($objAuthAdapter);
if ($objResult->isValid()) {
$this->_forward(\'ok\');
else {
$this->_forward(\'false\');
}
}
Dodajemy metody {stala}okAction(){/stala} oraz {stala}falseAction(){/stala},
do których przekierowuje {stala}metoda _forward(){/stala}:
public function okAction() {
}
public function falseAction() {
}
oraz widoki:
ok.phtml:
Logowanie powiodło sięfalse.phtml:
Logowanie nie powiodło się
Plik {stala}check.phtml{/stala} zostawiamy pusty (może
w przyszłości się przyda – pozostawiam to twojej
inwencji). Na rysunkach 2 oraz 3 zaprezentowano
wynik poprawnego oraz niepoprawnego logowania.
Trwałość
Zend_Auth pozwala także na przechowywanie
informacji o zakończonym powodzeniem logowaniu,
tak abyś mógł sprawdzić na innych stronach
czy i jaki użytkownik jest zalogowany. W tym celu
musisz się jednak zapoznać z modułem Zend_Session.
Na szczęście w najbardziej podstawowym
przypadku Zend_Auth robi wszytko za nas. Wystarczy
że wystartujesz sesje. W tym celu do w pliku
index.php dodajemy:
require_once \'Zend/Session.php\';
Zend_Session::start();
Teraz Zend_Auth po udanej autoryzacja zapisze
o tym informację w sesji, dzięki czemu za pomocą
metody {stala}hasIdentity(){/stala} możemy sprawdzić, czy klient
jest zalogowany. Zmień teraz metody {stala}okAction(){/stala}
oraz {stala}falseAction(){/stala}:
public function okAction() {
$objAuth = Zend_Auth::getInstance();
if (!$objAuth->hasIdentity()) {$this->_forward(\'false\');
}
}
public function falseAction() {
$objAuth = Zend_Auth::getInstance();
if ($objAuth->hasIdentity()) {$this->_forward(\'ok\');
}
}
Jeśli tego potrzebujemy, metoda {stala}getIdentity(){/stala}
zwróci nam nazwę zalogowanego użytkownika.
Następnie wywołaj strony {stala}http://twojadomena/login/ok{/stala} oraz {stala}http://twojadomena/login/false{/stala} przed
i po zalogowaniu i obserwuj, jak zachowuje się
gotowa aplikacja.
I co dalej?
To tylko drobny wycinek możliwości Zend_Auth. Jeśli zechcesz, możesz napisać własne
adaptery (bądź korzystać z innych wbudowanych
adapterów, np. {stala}Zend_Auth_Adapter_Digest{/stala} czy
{stala}Zend_Auth_Adapter_Ldap{/stala}). Możesz też oprogramować
własny sposób zapewnienia trwałości, jeśli
ten oparty na sesji cię nie zadowala.
Wszystkie możliwości Zend_Auth zostały opisane
w dokumentacji znajdującej się pod adresem
http://framework.zend.com/manual/en/zend.auth.html. Zachęcamy do samodzielnego eksperymentowania
z kodem.
Zend_Auth
Moduł Zend_Auth mimo prostego zadania jakie
ma spełniać, jest dużym modułem, a co więcej,
oferuje spore możliwości rozbudowy. My zaprezentujemy
jedynie najważniejsze jego możliwości,
ponieważ dogłębne jego poznanie wymagałoby
poświęcenia całej serii artykułów. Nie martw się
jednak – jest to prosty moduł, a informacje na jego
temat są łatwo dostępne.
Klasa Zend_Auth jest singletonem (czym jest
singleton dowiesz się z Internet Makera 1/07 lub
z serwisu magazynyinternetowe.pl – http://serwis.magazynyinternetowe.pl/artykul/685,1,643,wzorce_projektowe_-_singleton.html), nie można
utworzyć więc na jej podstawie obiektu za pomocą
operatora new. Co więcej, istnieje zawsze tylko
jeden obiekt tej klasy dla całej aplikacji. Aby utworzyć
obiekt klasy Zend_Auth, należy skorzystać ze
statycznej metody {stala}getInstance(){/stala}:
require_once \'Zend/Auth.php\';
$objAuth = Zend_Auth::getInstance();
W celu wykonania identyfikacji klienta, Zend_Auth używa tak zwanych adapterów. To wybór
adaptera decyduje o tym gdzie i jak przechowywane
są takie dane o użytkownikach, jak ich nazwa (login)
i hasło. Jako że najczęściej w tym celu wykorzystywana
jest baza danych, użyjemy w naszym przykładzie
adaptera {stala}Zend_Auth_Adapter_DbTable{/stala}.
Jego konstruktor przyjmuje cztery parametry:
adapter z połączenia z bazą danych, nazwę tabeli
przechowującej informacje o użytkownikach,
nazwę kolumny z nazwami użytkowników, a także nazwę kolumny z hasłami:
$objAuthAdapter = new Zend_Auth_Adapter_DbTable($objDbAdapter, \'users\',\'username\', \'password\');
Nie będziemy tutaj wnikali w szczegóły
dotyczące adaptera połączenia z bazą danych.
Stworzymy po prostu jego obiekt:
$objDbAdapter = new Zend_Db_Adapter_Pdo_Mysql(array(\'host\' => \'127.0.0.1\',\'username\' => \'root\',\'password\' => \'\',\'dbname\' => \'users\'));
Załóżmy jeszcze na nasze potrzeby tabelę przechowującą
dane o użytkownikach (nie zapomnij
wypełnić jej przykładowymi danymi):
CREATE TABLE users (id INT NOT NULL auto_increment, username VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, PRIMARY KEY(id) );
Gdy mamy już obiekt adaptera {stala}Zend_Auth_Adapter_DbTable{/stala}, możemy przekazać do niego
nazwę użytkownika oraz hasło:
$objAuthAdapter->setIdentity(\'nazwa użytkownika\') ->setCredential(\'hasło\');
Teraz obiekt adaptera przekazujemy do
obiektu klasy Zend_Auth i dokonujemy
sprawdzenia:
$objResult = $objAuth->authenticate($objAuthAdapter);
Metoda {stala}authenticate(){/stala} zwraca obiekt klasy
{stala}Zend_Auth_Result{/stala}, który przechowuje informacje
o rezultacie sprawdzania poprawności podanych
przez użytkownika danych. Możliwe rezultaty to:
- {html}Zend_Auth_Result::SUCCESS{/html} – logowanie powiodło się,
- {html}Zend_Auth_Result::FAILURE{/html} – logowanie nie powiodło się,
- {html}Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND{/html} – niepoprawna nazwa użytkownika,
- {html}Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS{/html} – niejednoznaczna nazwa użytkownika,
- {html}Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID{/html} – niepoprawne hasło,
- {html}Zend_Auth_Result::FAILURE_UNCATEGORIZED{/html} – inny błąd podczas logowania.
Kod rezultatu możesz poznać używając metody
getCode(), np.:
$objResult = $objAuth->authenticate($objAuthAdapter);
switch ($objResult->getCode()) {
case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
//niepoprawny login lub hasło
break;
case Zend_Auth_Result::SUCCESS:
//logowanie powiodło się
break;
default:
//inny błąd
break;
}
Klasa {stala}Zend_Auth_Result{/stala} posiada jeszcze
jedną interesująca metodę – {stala}isValid(){/stala}. Zwraca ona
wartość true tylko wówczas, gdy logowanie przebiegło
poprawnie, co zdejmuje z nas konieczność
testowania wartości zwróconych przez metodę
{stala}getCode(){/stala}.