Overovani uzivatele pri kazdem pristupu

- George
 - Člen | 8
 
Zdravim,
s Nette zacinam a placam se v nem asi tyden. Podle Quickstartu a prirucky
uz jsem neco spachal a udelal jsem i autentizaci. Bohuzel to co jsem podle
dokumentace spachal ma zasadni nedostatek a sice, ze se uzivatel overi jen pri
prihlaseni a pak uz ne. Takze pokud se po jeho prihlaseni cokoliv v db zmeni
(heslo, datum platnosti uctu, admin ho zablokuje), tak uzivatel zustava
prihlaseny.
Resim vlastne uplne stejny problem jako v 4 roky starem, jiz uzamcenem vlakne,
kde ale nevzeslo zadne ciste reseni https://forum.nette.org/…dem-pristupu
Nebo aspon ja ho z toho nevycetl ;)
Diky za nakopnuti.

- ZZromanZZ
 - Člen | 87
 
Identita je v session, a pokud bys chtěl ověřovat práva nebo existenci
uživatele musíš šahat do db při každém požadavku.
Viz třeba tohle vlákno

- David Matějka
 - Moderator | 6445
 
abys mel porad aktualni identitu, staci par veci: upravit UserStorage (resp.
metodu getIdentity) a vytvorit si vlastni tridu pro identitu, inspirace jak to
pouzivam ja:
UserStorage.php
<?php
class UserStorage extends \Nette\Http\UserStorage
{
	protected $userDao;
	public function __construct(\Nette\Http\Session $session,
			\Models\UserDao $userDao)
	{
		parent::__construct($session);
		$this->userDao = $userDao;
	}
	public function getIdentity()
	{
		$id = parent::getIdentity();
		if ($id and $id instanceof Identity and !$id->isLoaded()) {
			$this->userDao->loadIdentity($id);
		}
		return $id;
	}
}
Identity.php
<?php
class Identity extends \Nette\Object implements \Nette\Security\IIdentity{
	protected $id;
	protected $loaded = false;
	protected $roles = array();
	protected $username;
	protected $email;
	.....
	public function __construct($id){
		$this->id = $id;
	}
	public function __sleep(){
		return array("id");
	}
	public function __wakeup(){
		$this->loaded = false;
	}
	public function isLoaded(){
		return $this->loaded;
	}
	//...gettery, settery
}
userdao uz je potom nejakej tvuj model, kterej bude mit metodu loadIdentity a postara se o jeji nacteni
pak budes muset nastavit tenhle UserStorage jako sluzbu (prepsat defaultni userstorage). ted nevim, jestli to jde v neonu, kdyztak takhle:
services:
	nette.userStorage: UserStorage
jinak pres compiler extension
$builder->removeDefinition("nette.userStorage");
$builder->addDefinition($this->prefix("userStorage"))
	->setClass("UserStorage");
				
- George
 - Člen | 8
 
Tak jsem to zatim nejak zbastlil (urcite uplne spatne co se filozofie Nette
tyce ) :)
Casem snad do Nette vice proniknu, zjistim, ze jsem to udelal uplne spatne a
udelam to jinak.
Ted to ale funguje.
Samozrejme uvitam pokud nekdo poradi neco lepsiho, ale nevim jestli to aktualne
pochopim :)
V modelu Authenticator.php jsem vyrobil funkci
<?php
	.....
	public function isIdentityValid(\Nette\Security\IIdentity $identity)
	{
		$userData = $this->database->table('users')->where('id', $identity->getId())->fetch();
		if ($userData &&
			$userData->username == $identity->username &&
			$userData->password == $identity->password &&
			$userData->disabled == $identity->disabled &&
			$userData->role     == $identity->role)
		{
			return TRUE;
		} else {
			return FALSE;
		}
	}
?>
a volam ji z BasePresenteru, ktery vypada takto:
<?php
use Nette\Security\User;
/**
 * Base presenter for all application presenters.
 */
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	/** @var Authenticator */
	private $auth;
	public function inject(Authenticator $auth)
	{
		$this->auth = $auth;
	}
	protected function startup()
    {
        parent::startup();
		if ($this->name != 'Sign') {
			if ($this->getUser()->isLoggedIn()) {
				$this->checkUserIdentity();
			}
			if (!$this->getUser()->isLoggedIn() && $this->getUser()->getLogoutReason() === User::INACTIVITY) {
				$this->flashMessage('Došlo k odhlášení z důvodu neaktivity.');
			}
			if (!$this->getUser()->isLoggedIn()) {
				$this->redirect('Sign:in', array('backlink' => $this->storeRequest()));
			}
		}
    }
	public function checkUserIdentity()
    {
		if (!$this->auth->isIdentityValid($this->getUser()->getIdentity())) {
			$this->handleSignOut('Nesouhlasí identita uživatele. Přihlašte se prosím znovu.','error');
		}
	}
	public function handleSignOut($msg = 'Odhlášení bylo úspěšné.', $type = 'success')
    {
		$this->getUser()->logout(TRUE);
		if ($msg) { $this->flashMessage($msg,$type); }
		$this->redirect('Sign:in', array('backlink' => $this->storeRequest()));
    }
}
?>