Problém s autorizací a backlinkem
- Facedown
- Člen | 38
Ahoj, mírně jsem si poupravil Authorizator dle zdejšího fóra. Vše
funguje tak jak očekávám, nicméně, pokud dojde k
$this->restoreRequest($this->backlink); nastane problém.
Nebo alespoň myslím, že je to tímhle.
Můj kód:
<?php
namespace Base\Model;
use Nette\Application\UI\Presenter;
use Nette\Security\IAuthorizator;
class Authorization implements IAuthorizator {
private $presenter;
private $authorization;
public function __construct(Presenter $presenter, IAuthorizator $authorization) {
$this->presenter = $presenter;
$this->authorization = $authorization;
}
public function isAllowed($role, $name, $action) {
$signal = $this->presenter->getSignal();
if($this->isSignalFromPresenter($signal))
$action = $signal[1] . '!';
elseif($this->isSignalFromComponent($signal)) {
$name = $name . ':' . $signal[0];
$action = $signal[1] . '!';
}
return $this->authorization->isAllowed($role, $name, $action);
}
private function isSignalFromPresenter($signal) {
return $signal && empty($signal[0]);
}
private function isSignalFromComponent($signal) {
return $signal && $signal[0];
}
}
<?php
namespace App\Base\Presenters;
use Base\Model\Authorization;
abstract class BasePresenter extends \Nette\Application\UI\Presenter {
use \Nextras\Application\UI\SecuredLinksPresenterTrait;
protected function checkAcl() {
$authorization = new Authorization($this, $this->user->getAuthorizator());
$this->user->setAuthorizator($authorization);
if(!$this->user->isAllowed($this->getName(), $this->getAction())) {
$this->flashMessage('Přístup odepřen. Prosím, přihlaste se');
$this->redirect('Prihlaseni:', ['backlink' => $this->storeRequest()]);
$this->redirect('Default:');
}
}
protected function startup() {
parent::startup();
$this->checkAcl();
}
}
Jakmile jako nepřihlášený uživatel zadám cestu k /ucet/, tak mě to
úspěšně přesměruje na přihlašovací stránku a do URL se přidá
backlink, ale jakmile se přihlásím, dostanu tuto hlášku:
Nette\InvalidStateException
Resource ‚Front:Ucet:prihlaseniForm-form‘ does not exist.
Tento resource v Ucet neexistuje, to je pravda, nicméně nevím, proč se mi tam objevuje Ucet. Už nevím jak z toho ven. Popřípadě, pokud byste měli lepší řešení pro autorizaci, byl bych rád za radu.
Děkuji.
- Facedown
- Člen | 38
@Unlink
<?php
namespace App\FrontModule\Presenters;
class PrihlaseniPresenter extends BasePresenter {
/** @var \App\FrontModule\Forms\LoginFormFactory @inject */
public $form;
/** @persistent */
public $backlink = '';
/** @var \App\FrontModule\Components\FacebookLoginControlFactory @inject */
public $facebookLoginControl;
public function actionDefault() {
if($this->user->isLoggedIn()) {
$this->flashMessage('Již jsi přihlášen', 'warning');
$this->redirect('Default:');
}
}
protected function createComponentPrihlaseniForm() {
$form = $this->form->create();
$form->onSuccess[] = function() { $this->onSuccessLogin(); };
return $form;
}
protected function createComponentFacebookLoginControl() {
$control = $this->facebookLoginControl->create();
$control->onSuccess[] = function() { $this->onSuccessLogin(); };
return $control;
}
private function onSuccessLogin() {
$this->flashMessage('Přihlášení bylo úspěšné', 'success');
$this->restoreRequest($this->backlink);
$this->redirect('Default:');
}
}
<?php
namespace App\FrontModule\Forms;
use Nette\Application\UI\Form;
use App\BaseModule\Forms\IFormFactory;
class LoginForm extends \Nette\Application\UI\Control {
public $onSuccess;
private $form;
const TEMPORARY_LOGIN = ["+ 30 minutes", true];
const PERMANENT_LOGIN = ["+ 14 days", false];
public function __construct(IFormFactory $f) {
$this->form = $f;
}
public function render() {
return $this['form']->render();
}
public function processForm(Form $form) {
try {
$values = $form->getValues();
$this->sessionTimer($values);
$this->presenter->getUser()->login($values->email, $values->password);
$this->onSuccess();
} catch(\Nette\Security\AuthenticationException $ex) {
$this->presenter->flashMessage($ex->getMessage(), 'danger');
}
}
private function sessionTimer($values) {
if($this->isSetPermanentLogin($values))
$this->presenter->getUser()->setExpiration(...self::PERMANENT_LOGIN);
else
$this->presenter->getUser()->setExpiration(...self::TEMPORARY_LOGIN);
}
private function isSetPermanentLogin($values) {
return isset($values->remember);
}
protected function createComponentForm() {
$form = $this->form->create();
$form->addProtection();
$this->addEmail($form);
$this->addPassword($form);
$this->addRemember($form);
$form->addSubmit('signIn', 'Přihlásit');
$form->onSuccess[] = function() use ($form) {
$this->processForm($form);
};
return $form;
}
private function addEmail(Form $form) {
$form->addText('email', 'E-mail')
->setType('email')
->addRule(Form::FILLED, '%label musí být vyplněn')
->addCondition(Form::FILLED)
->addRule(Form::EMAIL, '"%value" není email');
}
private function addPassword(Form $form) {
$form->addPassword('password', 'Heslo')
->addRule(Form::FILLED, '%label musí být vyplněné');
}
private function addRemember(Form $form) {
$form->addCheckbox('remember', 'Trvalé přihlášení');
}
}
Editoval Facedown (3. 7. 2015 17:17)
- Facedown
- Člen | 38
V přípdadě, že místo rozhraní IAuthorizator tam dám přímo Permission, tak dostávám tuto chybu:
Recoverable Error
Argument 2 passed to Base\Model\Authorization::__construct() must be an instance of Nette\Security\Permission, instance of Base\Model\Authorization given, called in C:\xampp\htdocs\Argue\app\BaseModule\presenters\BasePresenter.php on line 11 and defined
Zdá se tedy, že je již nastaven ten můj authorizator, přičemž k danému setteru se ještě v kódu ani nedošlo. Vůbec nevím jak z toho.
- Unlink
- Člen | 298
Ten spôsob akým používaš ten authorizátor nebude najsprávnejší, mal
by si ten svoj registrovať cez DI a tomu Permission
nastaviť autowired: no
Len teraz neviem, ako by si tam dostal presenter…
Tá tvoja druhá chyba, mi pripadá tak, akoby si ten tvoj autorizátor nastavil Userovi 2× čo môže potom spôsobiť aj ten prvý problém.
Ja by som ti odporúčal, tu logiku čo máš v isAllowed
presunúť do tej metódy checkAcl
a môžeš potom používať ten
Permission
authorizator.
- Facedown
- Člen | 38
Unlink napsal(a):
Ten spôsob akým používaš ten authorizátor nebude najsprávnejší, mal by si ten svoj registrovať cez DI a tomu Permission nastaviť
autowired: no
Len teraz neviem, ako by si tam dostal presenter…
Tá tvoja druhá chyba, mi pripadá tak, akoby si ten tvoj autorizátor nastavil Userovi 2× čo môže potom spôsobiť aj ten prvý problém.
Ja by som ti odporúčal, tu logiku čo máš v
isAllowed
presunúť do tej metódycheckAcl
a môžeš potom používať tenPermission
authorizator.
Pokud bych tu logiku přesunul do BasePresenteru do metody checkAcl, tak jak bych potom mohl používat Authorizator v šablonách?
- Facedown
- Člen | 38
Unlink napsal(a):
A prečo by nefungoval? lebo nechápem načo potrebuješ v šablóne kontrolovať oprávnenia vzhľadom na aktuálny signál?
Já jsem to nezkoušel, ale co když mám takovou URL:
/www/argue/1/?argueControl-id=1&do=argueControl-like&argueControl-_sec=092ab582
Je to odkaz pro like, takže bych požadoval, že když uživatel nebude přihlášen (mít oprávnění), tak aby třeba místo odkazu byl šedý palec nebo něco v tom smyslu.
- Unlink
- Člen | 298
no ale to ani ten tvoj kód nerieši keďže kontroluje len akutálny
signál $this->presenter->getSignal()
public function isAllowed($role, $name, $action) {
$signal = $this->presenter->getSignal();
if($this->isSignalFromPresenter($signal))
$action = $signal[1] . '!';
elseif($this->isSignalFromComponent($signal)) {
$name = $name . ':' . $signal[0];
$action = $signal[1] . '!';
}
return $this->authorization->isAllowed($role, $name, $action);
}
Ako máš momentálne definované resources?
Je to odkaz pro like, takže bych požadoval, že když uživatel nebude přihlášen (mít oprávnění), tak aby třeba místo odkazu byl šedý palec nebo něco v tom smyslu.
Podľa toho treba definovať tie resorce, a potom tam pridať napríklad
{if $user->isAllowed('likeControll', 'add')}