Ověření platnosti autentizace při každém přístupu
- DocX
- Člen | 154
Ahoj,
řeším problém s autentizací, kdy potřebuji, aby se při každém
požadavku na stránku znovu ověřilo, zda uživatel může být přihlášen
(např. pokud mezitím administrátor uživatele nezablokoval, nesmazal,
nesnížil práva apod.) a zároveň tím pokaždé aktualizovat uživatelská
data. Nejprve jsem chtěl extendnout třídu User
z Nette a
upravit implementaci funkce isAuthenticated
, při níž by se
vlastně volalo vnitřně authenticate. Něco ve smyslu:
<?php
class MyUser extends User
{
public function isAuthenticated()
{
$identity = $this->getIdentity();
try
{
$this->authenticate($identity->username, $identity->password);
}
catch(AuthenticationException $e)
{
return FALSE;
}
return parent::isAuthenticated();
}
}
?>
Jenže problém je v tom, že User::isAuthenticated
je
deklarovaná jako final
. Samozřejmě mohl bych vzít soubor se
třídou User
, zkopírovat, přejmenovat třídu na
MyUser
a upravit. Ale proč?
Případně máte nějaký jiný nápad jak tento problém řešit?
Díky :)
- vlki
- Člen | 218
No, nenapadá mne lepší přístup, ale možná jen jiný druh provedení. Přidat tam handler.
Patch s handlerem.
--- a/Nette/Web/User.php
+++ b/Nette/Web/User.php
@@ -59,6 +59,9 @@ class User extends /*Nette\*/Object implements IUser
/** @var array of function(User $sender); Occurs when the user is successfully authenticated */
public $onAuthenticated;
+
+ /** @var array of function(User $sender); Occurs when is checked if the user is authenticated */
+ public $onAuthenticationCheck;
/** @var array of function(User $sender); Occurs when the user is logged off */
public $onSignedOut;
@@ -136,6 +139,7 @@ class User extends /*Nette\*/Object implements IUser
*/
final public function isAuthenticated()
{
+ $this->onAuthenticationCheck($this);
$session = $this->getSessionNamespace(FALSE);
return $session && $session->authenticated;
}
Pak by sis jen před zavoláním metody isAuthenticated
zaregistroval nějaké callbacky. Třeba na model, který teď implementuje
IAuthenticator
. Tam by sis už mohl dělat prakticky cokoli:)
$user = Environment::getUser();
$userAuthenticator = new UserAuthenticator;
$user->onAuthenticationCheck[] = array($userAuthenticator, 'check');
if (!$user->isAuthenticated())
$this->redirect('pryc');
class UserAuthenticator extends Object implements IAuthenticator
{
...
public function check(User $user)
{
$identity = $user->getIdentity();
try {
$this->authenticate($identity->username, $identity->password);
} catch(AuthenticationException $e) {
$user->signOut();
}
}
...
}
- DocX
- Člen | 154
vlki napsal(a):
No, nenapadá mne lepší přístup, ale možná jen jiný druh provedení. Přidat tam handler.
Jo to je taky hezký :). Je to ale spíš už na začlenění přímo do
Nette. Já to nepotřebuji takto univerzální, takže jsem metodu
User::isAuthenticated()
udělal nefinální a pak ji přepsal ve
vlastní odvozené třídě.
Šlo mi spíše o to, proč tam to final
vůbec je, pořád mi
to nedává moc smysl :)
PS: to $user->signOut();
v ošetření vyjímky autentizace
není potřeba, protože to dělá na začátku přímo funkce
User::authenticate()
;)
Editoval DocX (18. 8. 2009 12:52)