Ako na autorizaciu pomocou anotaci
- duskohu
- Člen | 778
Caute snazim sa urobit autorizaciu pomocou anotaci. Bol by som rad keby ma niekto nakopol kto to ma riesene funkcne a ako. Ako mate riesene anotacie role, zdroje a operacie a ako to spracuvate cez checkRequirements. Zaujimalo by ma ako riesite autorizaciu na uroven metod. Napr.: na handle alebo action. Popripade na uroven komponent a ich handle. Bol by som rad za nejake nakopnutie. Pouzivan nette 2.1 dev
- besanek
- Člen | 128
Já osobně mám vlastní anotaci allowed, např.
@allowed(article,delete)
, kterou používám buď pro celý
presenter nebo action metody. Práva ověřuji jen na úrovni presenteru.
Implementaci mám nějak takto
public function checkRequirements($element) {
$annotations = $element->getAnnotations();
$rules = array();
if(isset($annotations['allowed'])){
$rules = $annotations['allowed'];
}
foreach($rules as $rule){
if(!$this->user->isAllowed($rule[0] , $rule[1])){
throw new \Nette\Application\ForbiddenRequestException();
}
}
}
- Šaman
- Člen | 2659
Já už bych nedoporučoval zkoušet přístup pomocí anotací. Na jednom projektu to mám a je s tím víc starostí, než užitku.
Pokud chceš v anotacích přímo definovat kdo kam může:
- oprávnění je rozházené po všech presenterech, není možné plošně nastavit/zakázat přístup
- v anotaci nemáš (rozumně jednoduše) k dispozici konkrétní zdroj a uživatele musíš tahat z contextu. V praxi to znamená, že nejsi schopen říct, že editovat uživatele může jenom každý sebe.
Pokud jen automatizuješ kontrolu všech akcí:
Nakonec jsem si vytvořil anotaci @secured nad celým presentrem, která mi zkontroluje alespoň statická práva na každou akci. (Jestli chceš, mohu poslat kód.) Veškerá nastavení oprávnění jsou v ACL, anotace pouze zajistí, že aktuální uživatel musí mít povolen přístup například ke zdroji „Homepage“ privilegium „default“. Jenže to kontroluje i každou komponentu a signál a ACl se mi tedy dost rozrostlo. Potřebuji pro každý presenter, pohled, komponentu a akci samostatně definovat přístup.
Navíc u zdrojů, kde chci kontrolovat jestli konkrétní uživatel má práva na tento konkrétní zdroj si to pak stejně musím překontrolovat ručně. (Tzn. anotace mi zajistí, že uživatel se dostane na editaci uživatele, ale pak si musím ručně zkontrolovat, jestli chce editovat sebe – to může – nebo někoho cizího, což nesmí.)
Navíc vzniká prostor pro WTF záseky, kdy jsem měl povolenou akci
'delete'
a stále mi to zakazovalo smazat zdroj, protože jsem to
volal signálem 'delete!'
. V ACL to ale není tak do očí
bijící a blbě se v tom hledá chyba.
⇒ příště si budu hlídat práva ručně a bude mi stačit několik málo zdrojů a oprávnění.
Editoval Šaman (14. 7. 2013 18:14)
- Šaman
- Člen | 2659
Tohle mám v BasePresenteru.
Použití je takové, že každý presenter s anotací @secured
si
sám hlídá práva podle ACL. Nevýhody jsem už zmiňoval – musíš
vytvořit zdroj podle každé komponenty a dá uživateli oprávnění
submit!
apod. Na této úrovni neřeším tedy přístup ke zdroji
(entitě), ale k akci/handleru daného presenteru či komponenty.
<?php
/**
* Ověření oprávnění.
*/
public function checkRequirements($element)
{
// pokud má presenter anotaci @secured, zkontrolujeme statická oprávnění
if ($this->reflection->getAnnotation('secured'))
{
// jedná se o akci presenteru
if ($this->signal === NULL)
{
$resource = $this->name;
$action = $this->action;
}
// jedná se o signál presenteru
elseif ($this->signal && empty($this->signal[0]))
{
$resource = $this->name;
$action = $this->signal[1] . "!";
}
// jedná se o signál komponenty
elseif ($this->signal && $this->signal[0])
{
$resource = $this->signal[0];
$action = $this->signal[1] . "!";
}
// tohle by nemělo nikdy nastat
else
{
throw new InvalidStateException("Volaná akce není v presenteru, ani komponentě!");
}
// zkontrolujeme práva
if (!$this->user->isAllowed($resource, $action))
{
$this->flashMessage('Nemáte potřebná oprávnění pro tuto akci.');
if ($this->user->isLoggedIn())
{
$this->redirect('Homepage:default');
}
else
{
$this->redirect("Homepage:login");
}
}
}
}
?>
V ACL mám tedy např.
<?php
/* seznam uživatelských rolí */
$this->addRole('guest');
$this->addRole('user');
/* seznam zdrojů */
#presentery
$this->addResource('Homepage');
$this->addResource('User');
#komponenty
$this->addResource('loginForm');
$this->addResource('logoutControl');
$this->addResource('registrationForm');
$this->addResource('lostPasswordForm');
/* seznam pravidel oprávnění */
# nepřihlášený uživatel smí jen na registraci a login
$this->allow('guest', 'Homepage', array('login', 'registration', 'lostPassword', 'activate!', 'lostPassword!'));
$this->allow('guest', array('loginForm', 'registrationForm', 'lostPasswordForm'), 'submit!');
?>
P.S. Nekontroloval jsem, jestli někde není potřeba doplnit namespace –
ty mám všechny v use
sekci. Jinak by to mělo být funkční –
vykopíroval jsem to z projektu (Nette 2.1) a upravil jen specifické názvy na
obecné.
Editoval Šaman (14. 7. 2013 21:55)