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)