Nefungující redirect

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

Ahoj,
s touto situací jsem se setkal poprvé.

V startup() mam pro ověření jestli je uživatel přihlášen(je jenom jedna uroven uživatele, neni potřeba Role)

Tento kod:

if ($user->isAuthenticated()) {
		        $this->template->status = 'Prihlášen uživatel: '. $user->getIdentity()->getName();
		} else {
		        $this->template->status = 'Uživatel není přihlášen';
				Environment::getHttpResponse()->redirect($this->link('User:login'));
		}

Redirect se jakoby provede ale login() se nenačte. Firefox mi vyhodí chybu:

The page isn't redirecting properly
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.

Nevíte co to může způsobovat? Prosím o radu.

Díky moc.

Blizzy
Člen | 149
+
0
-

Co použít $this->redirect('User:login') (pro presenter) nebo $this->presenter->redirect('User:login') (v komponentě) namísto Environment::getHttpResponse()->redirect($this->link('User:login'))?

Editoval Blizzy (13. 8. 2009 16:32)

kravčo
Člen | 721
+
0
-

HttpResponse::redirect() nastavuje len hlavičku Location:, keby si za jeho volanie pripísal exit;, malo by to fungovať.

Určite lepším riešením je použiť na redirect vyšší mechanizmus – priamo prezenter:

if ($user->isAuthenticated()) {
    $this->template->status = 'Prihlášen uživatel: '. $user->getIdentity()->getName();
} else {
    $this->template->status = 'Uživatel není přihlášen';
    $this->redirect('User:login');
}

V tomto prípade exit; nie je potrebný, keďže v prezenteri je redirect obsluhovaný výnimkami…

jakubroz
Člen | 16
+
0
-

tak to vyhodí:

BadRequestException #404

Action name ‚/project/admin/document_root/‘ is not alphanumeric string.

Editoval jakubroz (13. 8. 2009 16:38)

Blizzy
Člen | 149
+
0
-

Jsi si jistý, že používáš $this->redirect('User:login'); a ne $this->redirect($this->link('User:login'));?

Editoval Blizzy (13. 8. 2009 16:39)

jakubroz
Člen | 16
+
0
-

Máte pravdu, opravdu jsem tam nechal to $this->link().

Ale když jsem to dal bez toho, tak vyskočí stejná chyba jako předtim. Ta z webového prohlížeče.

Zkusil sem to třeba v safari a to píše: Too many redirects occurred trying to open “http://localhost:8888/project/admin/document_root/”. This might occur if you open a page that is redirected to open another page which then is redirected to open the original page.

Blizzy
Člen | 149
+
0
-

To je potom problém někde v logice aplikace, přesměrovává se pořád a cyklus přesměrování se nezastaví, musí proto zakročit „vyšší síla“ :) a napsat too many redirects.

jakubroz
Člen | 16
+
0
-

Děkuji Vám. Už vím. jede to nějak takhle startup()->redirect()->startup()->redirect()

:-)

jakubroz
Člen | 16
+
0
-

Ale nastává teda otázka jak toto ověřit. Jak máte udělán login do administrace Vy? Do každé metody dáváte ověření zvlášť?

Nebo jestli jde v startup() nejak ověřit view…

Blizzy
Člen | 149
+
0
-

Login do administrace je pěkně popsaný v příkladech (examples) v distribuci v příkladu CD Collection.

Já mám udělaný BaseAdminPresenter, který potom dědí presentery v Admin modulu, vypadá takto (není to ještě úplně dokonalé, ale je to funkční):

abstract class BaseAdminPresenter extends BasePresenter {

	protected function startup() {
		$user = Environment::getUser();

		if (!$user->isAuthenticated()) {
			$backlink = $this->application->storeRequest();
			$this->redirect('Auth:login', $backlink);
		}

		parent::startup();
	}
}

EDIT: Ten tvůj template->status by se asi měl řešit pomocí flashMessage.

Editoval Blizzy (13. 8. 2009 17:22)

jakubroz
Člen | 16
+
0
-

To když udělam, tak to hodí Extra parameter for signal ‚Front_UserPresenter:renderlogin‘. Ten param v ty metodě na login nějak zpracovavas?

Editoval jakubroz (13. 8. 2009 16:58)

Blizzy
Člen | 149
+
0
-

Auth presenter vypadá shruba takto (je to z větší části dělané podle toho příkladu v distribuci):

class Admin_AuthPresenter extends BasePresenter {

	/** @persistent */
	public $backlink = '';

	public function actionLogout() {
		Environment::getUser()->signOut();
		$this->flashMessage('Byli jste odhlášeni.');
		$this->redirect('Auth:login');
	}

	public function actionLogin($backlink) {
		$this->template->title = 'Příhlášení';
	}

	/********************* loginForm *********************/

	public function createComponentLoginForm() {
		...
	}

	public function loginFormSubmitted($form) {
		try {
			$user = Environment::getUser();
			$user->authenticate($form['username']->value, $form['password']->value);

			$this->application->restoreRequest($this->backlink);
			$this->redirect('Dashboard:');
		} catch (AuthenticationException $e) {
			$form->addError($e->getMessage());
		}
	}
}

EDIT: V podstatě to pracuje tak, že při pokusu zajít do adimistrační části (presentery založené na BaseAdminPresenter) nepřihlášeného uživatele, se přesměruji na Login autentizačního prezenteru, ten dostane serializovaný původní request a po správném vyplnění autentizačního formuláře se tento request ($backlink) znovu obnoví (v tom případě vyhodí výjimku), pokud se request neobnoví (není vyhozena výjimka), provede se $this->redirect('Dashboard:');.

Editoval Blizzy (13. 8. 2009 17:05)

jakubroz
Člen | 16
+
0
-

No ted se v tom docela ztrácim.
Já mam všechny presentery v Front části, jelikož Front část webu neni vubec. Je to jenom administrace.

Blizzy
Člen | 149
+
0
-

To je jenom název modulu, na tom ani tak nezáleží, a pokud je modul jenom jeden, dá se říct, že je používání modulů zbytečné.

Jde o to, že všechny presentery ke kterým by měli přistupovat jen autentikovaní uživatelé jsou potomky BaseAdminPresenter, ve kterém je metoda startup(), která v případě neautentikovaného uživatele uloží request (do proměnné $backlink) a pošle ho uživatele na autentikaci do Auth:Login.

AuthPresenter je jediný presenter, který tuto metodu nedědí (protože by se přihlašování zacyklilo, když by tam přišel nepřihlášený uživatel). Jeho úkol v případě akce Login je zobrazení formuláře, který při zpracování autentikuje uživatele a přesměruje ho na původní request (který získá z persistentního parametru $backlink).

Editoval Blizzy (13. 8. 2009 17:23)

jakubroz
Člen | 16
+
0
-

takze metoda startup() bude jenom v DefaultAdminPresenteru a už nebude v DefaultPresenteru? jenom to přesunu…?

Blizzy
Člen | 149
+
0
-

Já tuto metodu startup() mám v abstraktní třídě BaseAdminPresenter, aby tuto metodu mohli zdědit všechny presentery, které vyžadují autentikovaného uživatele.

BaseAdminPresenter není „skutečný“ presenter, má jenom tu funkci, že ho někdo zdědí, proto je to abstraktní třída, která nemůže mít instance.

jakubroz
Člen | 16
+
0
-

Už to chápu. Moc diky. A funguje to!