Obsah
Nette\Web\User
Zajišťuje přihlašování a odhlašování uživatelů, popisuje jejich identitu a ověřuje práva na základě rolí.
Autentizace (přihlášení)
Přihlášení a odhlášení uživatele:
$user = new User;
// přihlášení
$user->login($userName, $password); // předáme přihlašovací jméno a heslo
// ověření, zda je uživatel přihlášen
if ($user->isLoggedIn()) ...
// jednoduché odhlášení
$user->logout();
Přihlašování vyžaduje u uživatele povolené cookies; jiná metoda přihlašování není bezpečná!
Oveření uživatelského jména a hesla provádí autentizační handler,
což je objekt implementující rozhraní
Nette\Security\IAuthenticator. Jeho triviální implementací je
třída Nette\Security\SimpleAuthenticator, která dostane
v konstruktoru seznam uživatelů a hesel jakožto asociativní pole. Úkolem
handleru je v metodě login(array $credentials) ověřit, zda
uživatelské jméno a heslo odpovídá a v případě úspěchu vrátit tzv.
identitu. Neúspěch indikuje vyhozením výjimky
Nette\Security\AuthenticationException s popisem důvodu. Lze
využít i připravené konstanty
IAuthenticator::IDENTITY_NOT_FOUND nebo
IAuthenticator::INVALID_CREDENTIAL.
$authenticator = new SimpleAuthenticator(array(
'john' => 'IJ^%4dfh54*',
'kathy' => '12345', // Kathy, this is very weak password!
));
$user->setAuthenticationHandler($authenticator);
Automatické odhlášení
Ve výchozím nastavení je uživatel odhlášen v okamžiku, kdy zavře
okno prohlížeče. Chování lze změnit metodou setExpiration().
První parametr určuje čas v sekundách, za který bude uživatel
v případě neaktivity odhlášen. Druhý parametr říká, zda uživatele
odhlásit v okamžiku zavření okna prohlížeče. Třetí parametr stanoví,
zda při odhlášení smazat identitu.
// uživateli zůstane při odhlášení identita
$user->logout(); // nebo $user->logout(FALSE);
// uživatelova identita bude smazána - hodí se u případů,
// kdy je počítač sdílený a chci se odhlásit
// a nezanechat po sobě žádné osobní údaje
$user->logout(TRUE);
// odhlásit uživatele po 14 dnech neaktivity
$user->setExpiration(1209600, FALSE);
// odhlásit uživatele po jednom dni neaktivity, nebo až zavře prohlížeč
$user->setExpiration(86400, TRUE);
// odhlásit uživatele až zavře prohlížeč (bez časového limitu)
$user->setExpiration(0, TRUE);
// automatické odhlášení uživatele po 15 minutách neaktivity
// nebo zavření prohlížeče s odstraněním identity
$user->setExpiration(15*60, TRUE, TRUE);
Pokud při ověřování autentizace uživatele zjistíme, že není přihlášen, můžeme jít ještě dál a zjistit příčinu odhlášení. Nette umožňuje zjistit metodou getLogoutReason() základní příčiny odhlášení jako zavření okna prohlížeče, neaktivita nebo manuální odhlášení uživatele. Můžeme tak například pomocí flash zpráviček dát uživateli vědět o příčině jeho odhlášení.
Z jakého důvodu byl uživatel odhlášen prozradí metoda
$user->getLogoutReason(). Pokud vypršel časový limit vrací
User::INACTIVITY, pokud uživatel zavřel okno prohlížeče vrací
User::BROWSER_CLOSED a pokud byl uživatel odhlášen voláním
metody logout() vrací User::MANUAL.
// user authentication
$user = Environment::getUser();
if (!$user->isLoggedIn()) {
if ($user->getLogoutReason() === User::INACTIVITY) {
$this->flashMessage('You have been logged out due to inactivity. Please login again.');
}
// stejným způsobem zjistíme User::BROWSER_CLOSED a User::MANUAL
}
Dále je možno využít událostí onLoggedIn a
onLoggedOut například pro jednoduchého přidání callbacku pro
logování autorizačních aktivit na webu. Událost onLoggedIn je
volána po úspěšném
přihlášení. Událost onLoggedOut je zpracována po
odhlášení uživatele, ať už se odhlásil sám nebo z důvodu neaktivity
či zavření prohlížeče.
$user->onLoggedIn[] = array($logger, 'loginMethod');
$user->onLoggedOut[] = array($logger, 'logoutMethod');
Expirace Nette\Web\Session musí být nastavena na stejnou nebo vyšší hodnotu, jakou má expirace přihlášení
Identita
Identita je objekt implementující rozhraní
Nette\Security\IIdentity. Nette\Web\User jej udržuje v session.
Jeho výchozí implementace Nette\Security\Identity udržuje
informaci o jméně, rolích a dalších uživatelských datech (na
uživatelská data si můžeme šáhnout přes
Environment::getUser()->getIdentity()->promena).
Ačkoliv má uživatel identitu, nemusí být přihlášený! Identita
se sice obvykle získá při přihlášení, ale i když vás systém po
nějaké době odhlásí ($user->logout()), stále si ji
pamatuje (jméno, obsah košíku na eshopu, …).
Pokud se to hodí, můžeme při odhlášení identitu vymazat:
$user->logout(TRUE).
Autorizace
Autorizace = zjištění, zda má uživatel právo to či ono udělat. Rozhoduje se na základě rolí a toho, zda je uživatel přihlášen. V nejjednodušších případech si vystačíme právě s indikátorem přihlášení:
if ($user->isLoggedIn()) ..
Silnější mechanismus je rozhodování na základě rolí:
- každý uživatel může mít v jednu chvíli přiřazeno více rolí
- nepřihlášený uživatel má automaticky roli
$user->guestRole(výchozí hodnota'guest') - autentizovaný (tj. přihlášený) uživatel bez identity má
automaticky roli
$user->authenticatedRole(výchozí hodnota'authenticated') - autentizovaný uživatel s identitou (
$user->getIdentity()) vychozí roli nezíská, o role se stará$user->getIdentity()->getRoles()
if ($user->isInRole('editor')) ..
S tím si u většiny Běžných Aplikací™ vystačíte.
Nejsilnější mechanismus poskytuje autorizační handler
($user->authorizationHandler), tj. objekt implementující
rozhraní Nette\Security\IAuthorizator s metodou
isAllowed(). Jeho implementací je právě třída Nette\Security\Permission,
do hry tak kromě rolí vstupují i parametery resource & privilege.
if ($user->isAllowed($resource, $privilege)) ..
Protože uživatel může mít více rolí, povolení dostane, pokud alespoň jedna role má povolení. Oba parametry jsou volitelné, výchozí hodnota nese význam všechny. Takže pokud např. parametr $privilege nevyužijeme, můžeme ho vynechat.
Ještě upozornění: pokud uživateli po odhlášení zůstane identita, tak
i včetně všech rolí – získatelných přes
$user->getIdentity()->getRoles(). Nicméně metoda
$user->getRoles() stav přihlášení zohledňuje. Stejně tak
i dotazy isInRole() a isAllowed() – proto je není nutné kombinovat
s dotazem isLoggedIn().
Odkud se handlery berou?
Globální úložiště pro služby (services) poskytuje Nette\Environment::getServiceLocator(), zkratkou pro získání objektu User je Environment::getUser(). Objekt Nette\Web\User má settery pro autorizační a autentizační handlery, ale aby to celé pracovalo hezky líně (tj. objekty se vytvářejí, až když jsou skutečně potřeba), pokouší se Nette\Web\User získat handlery opět přes metodu Nette\Environment::getService(), kde je identifikátorem název interface.
Stačí tedy nastavit:
Environment::getServiceLocator()->addService($authenHandler, 'Nette\Security\IAuthenticator');
Environment::getServiceLocator()->addService($authorHandler, 'Nette\Security\IAuthorizator');
// kde handler je buď hotový objekt (pak to ale není lazy), jméno třídy nebo callback na továrnu
Službu lze nastavit i skrze config.ini:
service.Nette-Security-IAuthenticator = MyAuthenticator
Více aplikací v jednom prostoru
V rámci jedné aplikace (serveru, session) může fungovat více aplikací, s tím, že si každá spravuje přihlašování samostatně. Stačí každé nastavit vlastní jmenný prostor:
$user->setNamespace('forum');
Viz také:



