Řešení autorizace pomocí anotací
- tomees
- Člen | 59
Ahoj, potřeboval bych poradit, resp. navést správným směrem, jak ověřovat pomocí anotací před metodou, zda k ní má uživatel oprávnění, pokud ne, vyhodit vyjímku. Docela by mi to ušetřilo práci, protože psát na začátku každé funkce „if..“ a celou podmínku je dosti zdlouhavé a vím, že by to pomocí těch anotací mělo jít. Díky
- Filip Procházka
- Moderator | 4668
https://doc.nette.org/…oli-a-zdroju a krmit to ze presenter::startup()
Editoval HosipLan (26. 10. 2010 11:15)
- Mikulas Dite
- Člen | 756
Tak můžeš zatím zaimprovizavat, třeba použít něco ve stylu tohohle (to jsem si psal nedávno, když jsem chtěl zkusit, jak je/není dlouhé):
class AnnotationRoles extends BaseModel
{
public static function verify($class, $method)
{
$roles = self::getRoles($class, $method);
if ($roles === FALSE) {
return FALSE;
}
if (!\is_array($roles)) {
$roles = array($roles);
}
foreach (\Nette\Environment::getUser()->getRoles() as $role) {
$key = array_search($role, $roles);
if ($key !== FALSE) {
unset($roles[$key]);
}
}
return count($roles) === 0;
}
private static function getRoles($class, $method)
{
try {
$class = new \Nette\Reflection\ClassReflection($class);
$method = $class->getMethod($method);
return $method->getAnnotation('secured');
} catch (\ReflectionException $e) {
return FALSE;
}
}
}
kde class má vyžadovat instanci presenter, to jsem tam zapomněl… Plus nějaká kontrola, jesli tam je ta metoda atp., ale to už nechám na tobě.
a kontrola v Protected / BasePresenteru
public function startup()
{
parent::startup();
if (!\Nette\Environment::getUser()->isLoggedIn()) {
$this->target = ':' . $this->getName() . ':' . $this->action;
$this->redirect('Sign:in', array('target' => $this->target));
}
$action = 'action' . ucfirst($this->action);
if (!\Model\AnnotationRoles::verify($this->presenter, $action)) {
$this->flashMessage('You don\'t have enough priviledges to do this.');
$this->redirect('Board:');
} else {
$this->flashMessage('debug: you have passed verification');
}
}
asi by to šlo napsat i lépe? Čekám, že hlavně ta část zjišťování annotací té akce.
Funguje to podle očekávání, tzn u akce jsou ty patřičné annotace (u renderu se nepočítají).
- Mikulas Dite
- Člen | 756
Už ti rozumím. No v tom případě můžeš rozšířit form (appform) a
tam volat ten verify
. Nebo, což je overkill, můžeš vylepšit
__call
(a asi i __invoke
) a volat to
verify()
tam.
- jtousek
- Člen | 951
@tomees: Už jsem to, o čem mluvíš pomocí anotací řešil. Mohu se zeptat, u jakých metod potřebuješ předem ověřit zda uživatel má dostatečná práva? jsou to akce presenteru, metody modelu nebo něco jiného?
Dále bych se chtěl zeptat ostatních na ty chystané anotace v Nette… Co si mám představit pod @roles? Že v anotaci definuju, které role mají na tuto akci právo? Pokud jo, pak mi uniká smysl – typicky chci, aby si administrátor pomocí GUI sám nadefinoval role (tedy jaká role co může a nemůže), které potom bude uživatelům přidělovat, takhle napevno to není vůbec žádný posun od pevné definice rolí pro objekt Permission. Co mi uniká?
Editoval jtousek (23. 11. 2010 22:44)
- srigi
- Nette Blogger | 558
@jtousek Vsak ono sa to nijak nevylucuje. Oznacis
nejaku metodu stylom allowedByShopManager
(napr. odobratie
produktu) a ty tu rolu iba dynamicky priradis nejakemu userovi.
Asi si to myslel opacnou logikou – nie user by mal dynamicky zoznam roli,
ale chranena metoda (allowedByShopManager
,
allowedByAdmin
, allowedByEmployye
). Ked sa ale nad tym
zasmyslis, zistis, ze nie metoda, ale skutocne user ma byt tym dynamickym prvkom
v app.
IMHO :)
- Mikulas Dite
- Člen | 756
@jtousek:
Předně doufám, že roles
je jenom dočasný název (přestože
i David ho na webexpu měl v prezentaci), mnohem výmluvnější je třeba
secured
. To jenom tak na okraj.
Roles by (podle mě) měli spíš znamenat výčet rolí, které jsou pro
danou akci (metodu) potřeba. Tzn and
místo or
. Máš
pravdu, že dynamické acl v tom udělat nejde, ale stejně nemáš kam
v dynamickém obsahu ty anotace psát. Dokážu si ale představit situaci, kde
administrace (hardcoded obsah) je ověřován pomocí anotací a ostatní práva
řešena jinde, resp. jinak.
Edit: @srigi:
To ale nefunguje, pokud jsou dynamicky i ty role, tzn. employee, boss, admin
nejsou hardcoded, nebo je potřeba přidat další skupinu.
Editoval Mikulas Dite (23. 11. 2010 22:57)
- jtousek
- Člen | 951
@srigi promin ale nemyslím, že jsi pochopil, co jsem měl na mysli (Mikulas Dite ano)… Nechci dynamicky přiřazovat role (tedy samozřejmě že jo, ale o to teď nejde), chci ty role dynamicky vytvářet a i měnit. Tzn. pro každou akci nechci mít ani tak výčet potřebných rolí, jako spíše výčet potřebných oprávnění.
Nyní to řeším tak, že název presenteru odpovídá resource a každá akce jeho odpovídá stejnojmenému privilege. Tedy pokud uživatel chce provést např. akci Category:update, musí mít oprávnění update nad zdrojem category. Bez ohledu na to, od které role toto oprávnění zdědil. Samozřejmě některé akce žádná oprávnění nepotřebují (např. zobrazení přihlašovacího formuláře), to řeším pomocí anotace @privilege false (lze mít buď u dané akce, nebo rovnou v anotacích presenteru pro všechny akce presenteru).