Redirect v BasePresenteru ve startup() → Příliž mnoho přesměrování
- thm
- Člen | 147
Ahoj,
jsem začátečník s nette a řeším „problém“, kde potřebuju, aby při
vstupu na kteroukoliv stránku aplikace, pokud enní uživatel přihlášen se
provede přesměrování na Sign:in. Tak jsem si tak říkal, že bych to mohl
napsat do startup() BasePresenteru:
abstract class BasePresenter extends Nette\Application\UI\Presenter{
public function startup() {
parent::startup();
if(!$this->getUser()->isLoggedIn()) $this->redirect('Sign:in');
}
}
Což ale způsobí chybu „Tato stránka obsahuje smyčku přesměrování“ – což je „možná asi“ i logický, pokud se aplikace při přesměrování znovu spouští. Když ten řádek s přesměrováním dám do Homepage:default, tak to samozřejmě funguje, ale já to potřebuju pro všechny stránky.
Jak se toto řeší, nebo co mi uniká? (po prohledávání fóra by se doporučuje to dát do startup() BasePresenteru pro „globální“ účinek)
- llsm
- Člen | 121
Musis kontrolovat tedy i jestli jsi na prihlasovaci strance a pokud ano, tak aby se redirect neprovedl. Neco jako:
<?php
if ((!$this->user->isLoggedIn()) && ($this->reflection->name != 'SignPresenter' && $this->getAction() != 'in')) $this->redirect('Sign:in');
?>
Dědit v urcitem presenteru od startup() v BasePresenteru bez volani parent::startup() neni mozne, tim padem to neni reseni, pokud nechces mit v aplikaci vic basepresenteru.
Editoval llsm (10. 4. 2013 14:20)
- thm
- Člen | 147
Díky za rychlou odpověď. Je to na mě moc obecně napsané.
K prvnímu způsobu: Mohl bys mi prosím nastínit, kam a jakou podmínku
napsat aby se pro Sign:in neprováděla kontrola ve startup() BasePresenteru
(jestli jsem to pochopil dobře?)
K druhému způsobu: Aha :) Tak si to zatím zkusím napsat pomocí dalšího
BasePresenteru
- hAssassin
- Člen | 293
@thm > Dukeovo reseni je lepsi. Pokud se jedna o admina tak kor (prakticky vsechny jsou zabezpeceny krom prihlasovaciho).
Ale obecne: mas nejaky BasePresenter
, z neho dedi
SignPresenter
(+ vsechny presentery ktere nemaji byt zabezpeceny) a
BaseSecuredPresenter
(z neho dedi pak vsechny ktere maji byt
zabezpecene, napr. MemberProfilePresenter
, apod.). No a tu tvoji
podminku pak das do BaseSecuredPresenter::startup()
.
Jako bonus pak muzes dat i do BaseSecuredPresenter
signal na
odhlaseni :)
- Nox
- Člen | 378
To je asi lepší způsob, osobně používám:
[BasePresenter] → (presentery nevyžadující přihlášení)
[BasePresenter] → [SecuredPresenter] → (presentery vyžadující
přihlášení)
test na autentikaci (no a i základní autorizaci) je pak prostě v SecuredPresenter::startUp(). V BasePresenteru je teda to, co je společné pro veřejné i neveřejné části.
- thm
- Člen | 147
Á výborně díky llsm za radu – toto jsem potřeboval. Já si myslel že
to nějak půjde zjistit kam se snažím lézt :) Paráda.
Jinak jsem si to mezitím napsal pomocí druhého BasePresenteru a to funguje
také. Ale pro pořádek (dle mého názoru) je asi lepší explicitní
podmínka, kdy zjišťuju na kterém presenteru:akci jsem.
Díky Vám oběma.
- llsm
- Člen | 121
hAssassin napsal(a):
@thm > Dukeovo reseni je lepsi. Pokud se jedna o admina tak kor (prakticky vsechny jsou zabezpeceny krom prihlasovaciho).
To je podle mne dost sporne. Ja vetsinu casu travim psani internich aplikaci,
ktere prakticky nemaji verejnou cast, tedy krome prihlasovaciho formulare.
A tam mi nejake zbesile neprehledne dedeni presenteru prijde horsi nez udelat
jednu osklivou podminku, nad kterou se sice clovek neznaly pozastavi, ale vcelku
brzy prijde na to, k cemu slouzi. Jinak by potreboval projit strukturu nekolika
presenteru, aby se dobral k tomu, proc to funguje zrovna takhle.
Navic u slozitejsich struktur se podobne veci resi vetsinou pomoci ACL a to je
pak cele jina pisnicka.
- hAssassin
- Člen | 293
@thm > sorry ale podminka je podle me cisty zlo, protoze:
- v podmince se ti vyskytuje primo nazev presenteru i akce, pokud se neco z toho rozhodnes menit musis upravovat nekolik souboru (prejmenovani, prepis presenteru, oprava podminky), kdezto v druhem pripade ti staci jen v prezenteru zmenit nazev tridy ze ktery dedi a je to.
- pokud mas jen jediny verejny presenter, tak OK, ale pokud jich mas treba vic (typicky Front je vetsina verejna, pouze par presenteru je neverejnych). To tam budes vypisovat skutecne vsechny presentery a akce? :-)
@llsm >
A tam mi nejake zbesile neprehledne dedeni presenteru prijde horsi nez udelat jednu osklivou podminku
Neprehledne dedeni? Vzdyt ti pribyde jen jediny presenter? co je na tom neprehlednyho? Naopak ta podminka je dost neprehledna protoze je zahrabana nekde v nejaky metode v nejakym souboru a to se pak tezko hleda. Navic je sama neprehledna, takze kdyz ji nekdo uvidi, rekne si „whaaat?“.
Navic u slozitejsich struktur se podobne veci resi vetsinou pomoci ACL a to je pak cele jina pisnicka.
Bacha, neplest si autentizaci (tedy overeni, zda je uzivatel prihlaseny) s autorizaci (coz dela ACL ;).
Editoval hAssassin (10. 4. 2013 16:07)
- Aurielle
- Člen | 1281
Kdyby se někomu zdála struktura BasePresenter → SecuredPresenter →
FooPresenter moc komplexní, dá se to vyřešit i tak, že v SignPresenteru
přetížíte metodu startup()
tak, že nebude volat
startup()
z vašeho BasePresenteru, ale přímo
z Nette\Application\UI\Presenter:
protected function startup()
{
// preskoci volani startup() v BasePresenteru, kde je podminka pro prihlaseni
Nette\Application\UI\Presenter::startup();
}
- hAssassin
- Člen | 293
@Aurielle > neni tohle trochu pekna prasarna? Jako fungovat to bude, ale neporusuje to vsechno co muze na dedicnosti? a jaky je pak logicky rozdil mezi tim mit dva base presentery? Tady jsou prece taky, jen jsou zkryty (resp jeden z nich je puvodni z nette).
Navic pres ty dva presentery (Base
a BaseSecured
)
to ma i dalsi vyhodu v tom, ze pro prihlaseny uzivatele obvykle potrebujes
i neco vic nez jen to overeni/presmerovani. Napr. ten
handleLogout()
jak sem zminoval vyse je presny kandidat, ktery ma v
BaseSecured
svoje misto (naopak v Base
nema co delat).
Nebo nejaka komponenta ktera se zobrazuje pouze prihlasenymu uzivateli, nejaky
specialni polozky menu, … A tady ta vyhoda uz je zrejma…
- llsm
- Člen | 121
Aurielle napsal(a):
Kdyby se někomu zdála struktura BasePresenter → SecuredPresenter → FooPresenter moc komplexní, dá se to vyřešit i tak, že v SignPresenteru přetížíte metodu
startup()
tak, že nebude volatstartup()
z vašeho BasePresenteru, ale přímo z Nette\Application\UI\Presenter
Páni, na jednu stranu mi to prijde hrozne pekny, na druhou stranu to prekonava nejednu uroven WTF. Rozhodne kdybych prisel k cizimu kodu, ktery by to takto mel, tak bych se asi dlouho chvili nechytal.
hAssassin napsal(a):
Navic pres ty dva presentery (Base a BaseSecured) to ma i dalsi vyhodu v tom, ze pro prihlaseny uzivatele obvykle potrebujes i neco vic nez jen to overeni/presmerovani. Napr. ten handleLogout() jak sem zminoval vyse je presny kandidat, ktery ma v BaseSecured svoje misto (naopak v Base nema co delat). Nebo nejaka komponenta ktera se zobrazuje pouze prihlasenymu uzivateli, nejaky specialni polozky menu, … A tady ta vyhoda uz je zrejma…
Tim logoutem jsi me asi presvedcil, ze to je i praktictejsi nez oskliva podminka. Diky
- duke
- Člen | 650
Ještě existuje jedna možnost a sice v BasePresenteru vyčlenit kontrolu a případnou redirekci do zvláštní metody (volané z BasePresenter::startup) a tuto metodu pak ve všech Presenterech, kde nechci tuto kontrolu, nebo ji chci nějak omezit, překrýt. Tj.
class BasePresenter extends Nette\Application\UI\Presenter
{
public function startup()
{
parent::startup();
$this->ensureAccessible();
}
protected function ensureAccessible()
{
if (!$this->getUser()->isLoggedIn()) $this->redirect('Sign:in');
}
}
… a v SignPresenteru mít:
protected function ensureAccessible()
{
if ($this->action !== 'in') parent::ensureAccessible();
}
- Jan Tvrdík
- Nette guru | 2595
llsm wrote:
Musis kontrolovat tedy i jestli jsi na prihlasovaci strance a pokud ano, tak aby se redirect neprovedl. Neco jako:
<?php if ((!$this->user->isLoggedIn()) && ($this->reflection->name != 'SignPresenter' && $this->getAction() != 'in')) $this->redirect('Sign:in'); ?>
Jen doplním, že místo $this->reflection->name
je
výrazně lepší zavolat $this->getName()
což vrací název
aktuálního presenteru.