Bezpečnost aplikace vs. komponenty – Part II
- uestla
- Backer | 799
Zdravím a rád bych navázal na toto vlákno.
V něm se již zmiňuji o tom, že používám ‚front control‘ ve startup BasePresenteru, kde kontroluji povolení k dané akci daného presenteru. Role a jim přidělená privilegia jsou pak deklarována v ACL.
Nicméně to neřeší ve zmiňovaném vlákně uvedený problém s odesíláním vhodných POST dat, díky čemuž se detekuje např. odeslání formuláře.
Dostal jsem nápad, že kromě akcí by se stejně daly zprivilegizovat
i signály. Problém je, jak je v kontrole odlišit od akcí, neboť prostým
odchycením názvu by došlo ke kolizi (actionRandom
vs.
handleRandom
). U signálu sem tedy přidal vykřičník (převzato
z odkazování na signál).
A konečně výsledný kód:
// BasePresenter:
protected function startup()
{
parent::startup();
$user = $this->user;
if (!$user->loggedIn && $user->logoutReason === User::INACTIVITY && $this->action !== 'logout') { // just inform the user about the logout
$user->logout(TRUE); // clear the identity
$this->flashMessage('You were automatically logged out due to your inactivity.');
$this->redirect('this');
}
if (!$user->isAllowed($this->name, $this->action)
|| ($this->signal !== NULL && !$user->isAllowed($this->name, $this->formatSignalString()))) {
if (!$user->loggedIn) {
$this->flashMessage('You have to sign in for this action.');
$user->logout(TRUE); // clear the identity
$backlink = $this->application->storeRequest();
$this->redirect('Homepage:', array(
'backlink' => $backlink,
));
} else {
$this->flashMessage('You\'re not permitted for this operation!', 'fail');
$this->redirect('Homepage:');
}
}
}
Důležitá je kontrola, zda byl poslán signál, stejně tak i metoda
formatSignalString()
:
protected function formatSignalString()
{
return $this->signal === NULL ? NULL : ltrim(implode('-', $this->signal), '-') . '!';
}
Ta připojuje – jak jsem psal výše – vykřičník za jméno signálu, který se „zaznamenává“ formou pole. Čili teď mi nic nebrání v tom si v ACL přímo určit, kdo může který formulář odesílat, dokonce na kterém presenteru (je-li definován v Base a chci, aby mohl posílat jen v Home:Base), apod.
Příklad:
// ACL (extends Nette\Security\Permission) : __construct():
$this->addRole('guest');
$this->addRole('admin');
$this->addResource('Homepage');
$this->addResource('Dashboard');
$this->allow('guest', 'Homepage', array('default', 'login', 'loginForm-submit!', 'myOwnSignal!'));
$this->deny('admin', 'Homepage', 'loginForm-submit!'); // prihlaseny se nemuze prihlasovat, to vi preci kazdy...
Co si o tomto řešení myslíte? Jsou v něm skrytá některá úskalí?