Bezpečnost aplikace vs. komponenty – Part II

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
uestla
Backer | 799
+
0
-

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í?

Jan Tvrdík
Nette guru | 2595
+
0
-

Vypadá to použitelně a bezproblémově.