Zend_Auth - uwierzytelnianie w Zend Framework

by Mateusz Tymek — on Zend Framework, PHP

Head's up! This post was written back in 2009 and is very likely to contain outdated information.

Tak jak obiecałem poprzednio, w tym artykule zaprezentuję działanie Zend_Auth na kilku przykładach.

Zend_Auth umożliwia programiście trzy podstawowe działania: sprawdzanie czy użytkownik podał właściwy login i hasło (uwierzytelnianie), sprawdzenie czy w danej chwili użytkownik jest zalogowany ("czy posiada tożsamość") oraz wylogowanie użytkownika ("wyczyszczenie tożsamości").

Podstawowe operacje

Zend_Auth jest klasą typu "singleton" - w aplikacji możemy mieć tylko jeden obiekt tego typu. Uzyskujemy go przy pomocy metody getInstance():

$auth = Zend_Auth::getInstance();

Uzyskaliśmy obiekt, sprawdźmy czy użytkownik jest aktualnie zalogowany:

if ($auth->hasIdentity()) {
    echo 'Użytkownik zalogowany.';
} else {
    echo 'Użytkownik niezalogowany.';
}

Gdy użytkownik wejdzie w odnośnik "wyloguj", aplikacja powinna wyczyścić jego tożsamość:

$auth->clearIdentity();

Najbardziej skomplikowaną czynnością jest sam proces uwierzytelniania.
Trzeba zdecydować gdzie będziemy przechowywać dane uwierzytelniające. Czy będzie to baza danych, katalog LDAP, a może pliki tekstowe? Za każdy z tych odpowiada tak zwany adapter, czyli klasa implementująca Zend_Auth_Adapter_Interface.
Mamy do wyboru kilka wbudowanych:

Uwierzytelnianie na podstawie tabeli w bazie danych.

Jest to najbardziej typowy sposób uwierzytelniania użytkowników, a więc rozwiązanie zaprezentuję właśnie na nim. Wyobraźmy sobie banalną tabelę w której przechowujemy loginy i hasła:

CREATE TABLE users (
    name     VARCHAR(40) NOT NULL,
    password VARCHAR(40) NOT NULL,
    PRIMARY KEY(name, password)
);

Proces logowania będzie polegał na utworzeniu obiektu klasy Zend_Auth_Adapter_DbTable, ustawieniu nazw tabeli i odpowiednich kolumn, a następnie na wywołaniu metody authenticate():

// Przykład zakłada że logowanie następuje gdy formularz logowania
// zostanie wysłany metodą POST
if ($request->isPost()) {

    // tutaj powinna nastąpić walidacja danych wejściowych
    (...)

    // utworzenie obiektu - $db jest obiektem klasy Zend_Db_Adapter
    $adapter = new Zend_Auth_Adapter_DbTable($db);

    // poinformowanie adaptera której tabeli i których kolumn ma używać
    $adapter
        ->setTableName('users')
        ->setIdentityColumn('name')
        ->setCredentialColumn('password');

    // podanie danych użytkownika
    $adapter
        ->setIdentity($request->getPost('username'))
        ->setCredential($request->getPost('password'));

    // w końcu - próba zalogowania
    $result = $auth->authenticate($adapter);


    if ($result->getCode() == Zend_Auth_Result::SUCCESS) {
        // sukces
        echo 'Logowanie powiodło się.';
    } else {
        // niepoprawne dane
        echo 'Logowanie nie powiodło się - podano niepoprawny login lub hasło.';
    }
}

Własne sposoby uwierzytelniania

Jeśli przechowujemy loginy i hasła w inny sposób (np w plikach tekstowych na oddzielnym serwerze) to będziemy musieli napisać własny adapter uwierzytelniający. Dość prosty przykład to adapter który akceptuje tylko jedeną parę nazwa użytkownika/hasło, zapisaną na stałe w kodzie PHP:

<?php
/**
 * Klasa AuthAdapterStatic
 *
 * Uwierzytelnia na podstawie statycznie zapisanej nazwy użytkownika
 * i hasła.
 *
 */

class AuthAdapterStatic implements Zend_Auth_Adapter_Interface
{
    protected $_username, $_password;
    // domyślna nazwa użytkownika i hasło
    protected $_validUsername = 'admin';
    protected $_validPassword = 'adminpass';

    /**
     * Konstruktor klasy.
     * Przyjmuje nazwę użytkownika i hasło
     *
     * @param string $username
     * @param string $password
     */
    public function __construct($username, $password) {
        $this->_username = $username;
        $this->_password = $password;
    }

    /**
     * Funkcja sprawdzająca czy podany login i hasło są poprawne.
     *
     * @return Zend_Auth_Result
     */
    public function authenticate()
    {
        if ($this->_username == $this->_validUsername
            && $this->_password == $this->_validPassword) {

            // Uwierzytelnianie powiodło się, informujemy o sukcesie.
            // Tożsamością użytkownika będzie nazwa podana jako parametr konstruktora.
            return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_username);
        }

        // Uwierzytelnianie nie powiodło się.
        // Zwracamy odpowiedni status, a jako tożsamość podajemy
        // wartość null.
        return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
    }
}

Adapter oprócz konstruktora przyjmującego nazwę użytkownika i hasło zawiera tylko jedną metodę: authenticate(). Zwraca ona obiekt klasy Zend_Auth_Result, który przechowuje informację o sukcesie lub niepowodzeniu logowania oraz tożsamość.

Tożsamość użytkownika

Tożsamość jest definiowana w klasie adaptera. Musi to być wartość jednoznacznie identyfikująca użytkownika (login, adres e-mail itp). Może to być również tablica lub obiekt.
Tożsamość jest przechowywana w sesji i można ją otrzymać w każdej chwili:

$identity = $auth->getIdentity();

W zaprezentowanych przykładach tożsamość jest łańcuchem tekstowym zawierającym nazwę użytkownika.

Przykład

Przykład to mała aplikacja pokazująca działanie Zend_Auth z własnym adapterem.

Pobierz przykład.


comments powered by Disqus