Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Nette Framework: Přihlašování uživatelů

Pomalu žádná webová aplikace se neobejde bez mechanismu přihlašování uživatelů a ověřování uživatelských oprávnění. Pojďme se podívat, jak tyto úlohy řeší Nette Framework.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Nejprve troška terminologie. Celé téma si rozdělíme do dvou okruhů: autentizace a autorizace. Pod autentizací se rozumí přihlašování uživatelů, tedy proces, při kterém se ověřuje, zda je uživatel opravdu tím, za koho se vydává. V drtivé většině aplikací se ověřuje uživatelské jméno a heslo. Naopak při autorizaci se zjišťuje, zda má již autentizovaný uživatel dostatečná oprávnění pro přístup k určitému souboru či pro provedení nějaké akce. Autorizaci si necháme do příštího pokračování.

Chcete se naučit o Nette víc?

Akademie Root.cz školení Vývoj webových aplikací v Nette Framework. Kurz je určen všem programátorům v PHP, kteří se chtějí naučit tvořit webové aplikace rychle a kvalitně, bez bezpečnostních děr. Jako aplikační rámec slouží Nette Framework. Školí sám autor Nette – David Grudl. Máte zájem o jiné školení? Napište nám!

Autentizace

Přihlašování uživatelů je oblast velmi úzce související s ochranou osobních údajů a zabezpečením aplikace. Jelikož PHP nenabízí žádnou standardní implementaci, jde také bohužel o oblast bezbřehé programátorské „kreativity“. Lze se setkat s odstrašujícími případy, kdy programátoři například ukládají hesla do cookies a nebo vytvářejí jiné sofistikované bezpečnostní díry.

Nette Framework se snaží tuto díru zacelit. A zároveň přihlašování zjednodušit až na naprosté minimum. Tím jsou dvě metody authenticate() (přihlásit) a signOut() (odhlásit), plus dotazovací metoda isAuthenticated() sdělující, zda je uživatel nyní přihlášen.

O realizační stránku se stará třída Nette\Web\User. Ta je, stejně jako v případě Nette\Web\Ses­sion, singleton, proto nevytváříme její instanci přímo, ale vrátí ji metoda Environment::getUser(). Používá se zhruba tímto způsobem:

require 'Nette/loader.php';

$user = Environment::getUser();

// přihlášení uživatele
$username = ...
$password = ...
$user->authenticate($username, $password);

// je přihlášen?
echo $user->isAuthenticated() ? 'ano' : 'ne';

// odhlášení
$user->signOut(); 

Aby příklad fungoval, je potřeba napsat rutinu, která provede ověření uživatelského jména a hesla. Této rutině se říká autentizační handler a jde o objekt implementující rozhraní Nette\Security\I­Authenticator. To má jedinou metodu authenticate(). Implementace, která ověřuje přihlašovací údaje oproti databázové tabulce, může vypadat třeba takto:

require 'Nette/loader.php';

// pokud používáte verzi pro PHP 5.3, odkomentujte následující řádek:
// use Nette\Object, Nette\Security\IAuthenticator, Nette\Security\AuthenticationException, Nette\Security\Identity;

class MyAuthenticator extends Object implements IAuthenticator
{

    public function authenticate(array $credentials)
    {
        $username = $credentials[self::USERNAME];
        $password = sha1($credentials[self::PASSWORD] . $credentials[self::USERNAME]);

        // přečteme záznam o uživateli z databáze
        $row = dibi::fetch('SELECT realname, password FROM users WHERE login=%s', $username);

        if (!$row) { // uživatel nenalezen?
            throw new AuthenticationException("User '$username' not found.", self::IDENTITY_NOT_FOUND);
        }

        if ($row->password !== $password) { // hesla se neshodují?
            throw new AuthenticationException("Invalid password.", self::INVALID_CREDENTIAL);
        }

        return new Identity($row->realname); // vrátíme identitu
    }

} 

Autentizační handler si zaslouží hlubší rozbor. Z pohledu návrhu aplikace podle vzoru MVP jde o součást modelu, přičemž samotnou autentizaci zpravidla iniciuje presenter. Nette Framework vás tak vede k oddělení ověření údajů od prezentační vrstvy.

Úkolem handleru je buď vrátit tzv. identitu v případě úspěchu, nebo vyhodit výjimku. Nette definuje výjimku Nette\Security\Au­thenticationEx­ception a několik chybových kódů, které můžete využít k formálnímu popisu vzniklé chyby. (Nicméně na to, jakou výjimku vyhodíte, se žádná omezení nekladou, nakonec bude je zachytávat a ošetřovat opět váš kód.)

V případě úspěšné autentizace vrácí handler identitu, což je objekt implementující rozhraní Nette\Security\I­Identity a popisující aktuálního uživatele. Popis může obsahovat libovolné údaje, povinné je uživatelské jméno (což nemusí být nutně totéž, jako přihlašovací jméno) a role (o těch si povíme více v příštím dílu). K identitě se dostaneme přes getter  getIdentity():

$user = Environment::getUser();
if ($user->isAuthenticated()) {
        echo 'Prihlášen uživatel: ', $user->getIdentity()->getName();
} else {
        echo 'Uživatel není přihlášen';
} 

Odhlášení

Jak už jsem zmínil, uživatele odhlásí metoda signOut(). Při odhlášení se však nesmaže uživatelská identita, kterou máme i nadále k dispozici. Pokud bychom chtěli identitu explicitně smazat, odhlásíme uživatele voláním  signOut(TRUE).

Kromě manuálního odhlášení nabízí Nette Framework i automatické odhlášení po uplynutí časového intervalu nebo zavření okna prohlížeče. K tomu slouží metoda setExpiration(), kterou volejte vždy před samotnou autentizací. Metoda setExpiration() jako parametr akceptuje relativní čas v sekundách nebo UNIX timestamp, v aktuální verzi frameworku je možné použít i velmi srozumitelný textový zápis. Druhý parametr stanoví, zda se má uživatel odhlásit při zavření okna prohlížeče:

// přihlášení vyprší po 30 minutách neaktivity nebo zavření okna prohlížeče
$user->setExpiration('+ 30 minutes');

// přihlášení vyprší po 2 dnech
$user->setExpiration('+ 2 days', FALSE); 

Dokonce je možné zjistit, z jakého důvodu k poslednímu odhlášení došlo (viz metoda  getSignOutReason).

Suma sumárum

Kompletní postup přihlašování uživatele pak vypadá asi takto:

require 'Nette/loader.php';

require 'MyAuthenticator.php';

// pokud používáte verzi pro PHP 5.3, odkomentujte následující řádek:
// use Nette\Environment, Nette\Security\AuthenticationException;

// přihlašovací údaje
$username = ...
$password = ...

$user = Environment::getUser();

// zaregistrujeme autentizační handler
$user->setAuthenticationHandler(new MyAuthenticator);

// nastavíme expiraci
$user->setExpiration('+ 30 minutes');

try {
        // pokusíme se přihlásit uživatele...
        $user->authenticate($username, $password);
        // ...a v případě úspěchu presměrujeme na další stránku
        Environment::getHttpResponse()->redirect('index.php');

} catch (AuthenticationException $e) {
        echo 'Chyba: ', $e->getMessage();
} 

Příště se podíváme na uživatelské role a ověřování uživatelských oprávnění.


Autor článku je vývojář na volné noze, specializuje se na návrh a programování moderních webových aplikací. Vyvíjí open-source knihovny Texy, dibi a Nette Framework a pravidelně pořádá školení pro tvůrce webových aplikací, které od podzimu 2009 nabídne kurz vývoje AJAXových aplikací.

David Grudl

David Grudl

David Grudl je autorem PHP knihoven Nette Framework, databázové vrstvy dibi a formátovače HTML kódu Texy!.

Školení Google+ pro firmy

DW - Školení PPC
  • Jak využít Google+ pro firemní komunikaci a marketing.
  • Čím se liší Google+ od Twitteru a Facebooku z pohledu firemního využití.
  • Jak využít Google+ v souladu s pravidly užívání.
  • Založení Google+ Page (Stránky) krok po kroku, včetně praktických tipů.

Detailní informace o školení Google+ »

Přehled názorů

RE: Nette Framework: Přihlašování uživatelů
aprilchild 19. 5. 2009 00:33
Nový
├ 
RE: Nette Framework: Přihlašování uživatelů
David Grudl 19. 5. 2009 00:40
Nový
│
└ 
RE: Nette Framework: Přihlašování uživatelů
aprilchild 19. 5. 2009 00:52
Nový
└ 
RE: Nette Framework: Přihlašování uživatelů
Lukáš Havrlant 19. 5. 2009 02:50
Nový
├ 
RE: Nette Framework: Přihlašování uživatelů
v6ak 19. 5. 2009 06:42
Nový
│
└ 
RE: Nette Framework: Přihlašování uživatelů
Mastodont 19. 5. 2009 07:59
Nový
│
 
├ 
RE: Nette Framework: Přihlašování uživatelů
v6ak 19. 5. 2009 08:03
Nový
│
 
└ 
RE: Nette Framework: Přihlašování uživatelů
Martin Hassman 19. 5. 2009 08:04
Nový
│
 
 
└ 
RE: Nette Framework: Přihlašování uživatelů
Mastodont 19. 5. 2009 11:11
Nový
│
 
 
 
└ 
RE: Nette Framework: Přihlašování uživatelů
Martin Štěpař 19. 5. 2009 12:06
Nový
vymodlený příspěvek
Játro 28. 5. 2009 01:12
Nový
└ 
Re: vymodlený příspěvek
MiKee 30. 5. 2009 19:46
Nový
 
└ 
Re: Re: vymodlený příspěvek
Játro 31. 5. 2009 22:09
Nový
 
 
└ 
Re: Re: vymodlený příspěvek
MiKee 12. 6. 2009 23:39
Nový
Tutorial.
Daniel Šintaj 9. 6. 2009 14:50
Nový
registrace autentizačního handleru
jar 17. 6. 2009 09:57
Nový
Řešení: Call to undefined method User::authenticate() .
Schmutzka 15. 11. 2010 10:29
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem