Chyba při přihlášení – vykreslí se jen část stránky

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

Ahoj,
řeším přihlašovací chybu. Když nastane chyba (=AuthenticationException), tak ji předám do formuláře a zobrazím. Na localhostu se stránka vykreslí celá, na produkčním serveru se utne v půlce. Pro ukázku dodávám screenshot.

Kód presenteru obstarávající login:

public function renderLogin($backlink)
{
	if(Environment::getUser()->isAuthenticated())
	{
		// User is already logged in
		$this->redirect(301, 'Default:');
	}

	$this->setTitle('Přihlášení');
}

protected function createComponentLogin($name)
{
	$form = new AppForm;

	$form->addText('username', 'Uživatelské jméno:')
		->addRule(Form::FILLED, 'Vyplňte prosím své uživatelské jméno.');
	$form->addPassword('password', 'Heslo:')
		->addRule(Form::FILLED, 'Zadejte prosím své heslo.');
	$form->addCheckbox('remember', 'Přihlásit trvale')->getControlPrototype()->class('checkbox');
	$form->addSubmit('login', 'Přihlásit se');
	$form->addProtection('Odešlete prosím formulář znovu, vypršel bezpečnostní token.');

	$form->onSubmit[] = array($this, 'userLogin');

	return $form;
}

public function userLogin(AppForm $form)
{
	$user = Environment::getUser();

	if($form['remember']->getValue())
	{
		$user->setExpiration('+ 7 days', FALSE);
	}
	else
	{
		$user->setExpiration('+ 2 hours');
	}

	try
	{
		$user->authenticate($form['username']->getValue(), $form['password']->getValue());
	}
	catch(AuthenticationException $e)
	{
		if($e instanceof UserBannedException)
		{
			$form->addError('Tento uživatelský účet byl zabanován administrátorem RuneScape Wiki. Není možné se na něj přihlásit.');
		}
		else if($e instanceof UserInactiveException)
		{
			$form->addError('Tento uživatelský účet není aktivní. Použijte prosím odkaz v e-mailu pro aktivaci vašeho účtu. V případě problémů kontaktuje administrátora RuneScape Wiki.');
		}
		else
		{
			$form->addError($e->getMessage());
		}

		return;
	}

	if(!$form->hasErrors())
	{
		$identity = $user->getIdentity();
		if($identity->user_rsnick)
		{
			$lastupdatetime = dibi::query('SELECT [last_update_time] FROM [users_highscores] WHERE [user_id] = %i', $identity->user_id)->fetchSingle();

			if(strtotime('+1 day', $lastupdatetime) < time())
			{
				RSWUser::updateHighscores($identity->user_rsnick, $identity->user_id);
			}
		}

		$this->getApplication()->restoreRequest($this->backlink);
		$this->flashMessage('Přihlášení bylo úspěšné. Vítejte.');
		$this->redirect(303, 'Default:');
	}
}

Kód authenticatoru:

class RSWAuthenticator extends Object implements IAuthenticator
{
	/**************** User role flags ****************/
	const USER = 1;
	const EDITOR = 2;
	const ADMINISTRATOR = 3;

	/**************** Activity flags ****************/
	const INACTIVE = 0;
	const ACTIVE = 1;
	const BANNED = 2;

	/**
	 * Authenticate user
	 * @param array $credentials
	 * @return Identity
	 * @throws AuthenticationException
	 */
	public function authenticate(array $credentials)
	{
		// Get the credentials
		$username = $credentials[self::USERNAME];
		$password = $credentials[self::PASSWORD];

		// Defined roles
		$role = array(
			self::USER => 'user',
			self::EDITOR => 'editor',
			self::ADMINISTRATOR => 'administrator',
		);

		// If any of required credentials is empty, throw exception
		if(empty($username) || empty($password))
		{
			throw new AuthenticationException('Jméno nebo heslo nemůže být prázdné.', self::INVALID_CREDENTIAL);
		}

		// Get user by username
		try
		{
			$userdata = RSWUser::get($username, RSWUser::USERNAME);
		}
		catch(UserNotFoundException $e)
		{
			throw new AuthenticationException('Zadaný uživatel neexistuje.', self::IDENTITY_NOT_FOUND);
		}

		// Hash the password and compare it
		$password = RSWUser::createHash($password, $salt); // $salt je tajná :P
		if($password !== $userdata->user_password)
		{
			throw new AuthenticationException('Bylo zadáno špatné heslo.', self::INVALID_CREDENTIAL);
		}

		// User is inactive...
		if(self::INACTIVE === (int) $userdata->user_active)
		{
			throw new UserInactiveException();
		}
		// or banned...
		if(self::BANNED === (int) $userdata->user_active)
		{
			throw new UserBannedException();
		}

		// Assign role
		$role = $role[$userdata->user_type];
		// Update lastvisit
		dibi::query('UPDATE [users] SET [user_lastvisit] = %i WHERE [user_id] = %i', time(), $userdata->user_id);
		$userdata->user_lastvisit = time();

		// Return identity
		return new Identity($userdata->username, $role, $userdata);
	}
}

Ještě jsem náhodně narazil na chybu, kde se děje něco s předčasným výstupem, ale myslím si, že je to serverem (po chvíli se chování vrátilo do normálu). Chyba je tady

Editoval gmvasek (10. 1. 2010 9:37)

Aurielle
Člen | 1281
+
0
-

V tom kódu musí být nějaký bug, změnil jsem chyby formuláře na flash zprávičky a teď na produkčním serveru nedostanu nic, na localhostu vše funguje…

Nette 0.9.2 stable
PHP 5.2.9-pl2-gentoo

Editoval gmvasek (9. 1. 2010 15:23)

Aurielle
Člen | 1281
+
0
-

Konkrétně to padá na vyhození jakékoliv výjimky v Authenticatoru…

edit: http://nezmar.jabbim.cz/…0/01/09.html#…

Editoval gmvasek (9. 1. 2010 15:27)

Aurielle
Člen | 1281
+
0
-

Zkoušel jsem pár dalších postupů a opravdu to padá na vyhození výjimky. Dokonce jsem nahradil celý kód authenticatoru tímto, ale výsledek je pořád stejný. Nějaké nápady? (Nette 0.9.2 revision b9fd602 released on 2009–11–12)

class SimpleAuthenticator extends Object implements IAuthenticator
{
	/**
	 * Authenticate user
	 * @param array $credentials
	 * @return Identity
	 * @throws AuthenticationException
	 */
	public function authenticate(array $credentials)
	{
		// Get the credentials
		$username = $credentials[self::USERNAME];
		$password = $credentials[self::PASSWORD];

		$users = array(
			'gmvasek' => 'nejakeheslo',
		);

		// If any of required credentials is empty, throw exception
		if(empty($username) || empty($password))
		{
			throw new AuthenticationException('Jméno nebo heslo nemůže být prázdné.', self::INVALID_CREDENTIAL);
		}

		if(!in_array($username, $users))
		{
			throw new AuthenticationException('not existing user');
		}

		if($users[$username] != $password)
		{
			throw new AuthenticationException('bad password');
		}

		// Return identity
		return new Identity($users[$username]);
	}
}
jasir
Člen | 746
+
0
-

Vyzkoušej nejnovější revizi Nette. Jinak je mi líto, nic mě nenapadá.

Ondřej Mirtes
Člen | 1536
+
0
-

Co na serveru pustit Laděnku?

medvedobijec
Člen | 11
+
0
-

Není to takhle náhodou stejný problém jako tady – https://forum.nette.org/…la-obrazovka ?

Aurielle
Člen | 1281
+
0
-

medvedobijec napsal(a):

Není to takhle náhodou stejný problém jako tady – https://forum.nette.org/…la-obrazovka ?

Ano, je. Když si to tak čtu, tak jim tohle pošlu do mailu, že stejný problém má více lidí. Jinak mě potěšilo, že i lidi z helpdesku umí aspoň základy Nette :)

Ondřej Mirtes napsal(a):

Co na serveru pustit Laděnku?

Výsledek žádný, jak už jsem psal, v odpovědi úplně chybí X-Powered-By: Nette Framework. V logu taky nic není, odzkoušeno včetně zapnutého $strictMode, zapnuté Laděnky na serveru a vypnutých $catchExceptions.

jasir napsal(a):

Vyzkoušej nejnovější revizi Nette. Jinak je mi líto, nic mě nenapadá.

Zkusím. Nejnovější revize to neřeší. Projevuje se stejná chyba.

Edit 2: tady jsou ještě jednou hlavičky požadavku + odpověď:

http://beta.runescapewiki.cz/uzivatel/prihlaseni?do=login-submit

POST /uzivatel/prihlaseni?do=login-submit HTTP/1.1
Host: beta.runescapewiki.cz
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; cs-CZ; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729) FirePHP/0.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: cs-CZ,cs;q=0.7,chrome://global/locale/intl.properties;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1250,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://beta.runescapewiki.cz/uzivatel/prihlaseni
Cookie: PHPSESSID=5d1f533ba80cb219be36bb65bd52d079; __utma=132823709.2084083459.1262105426.1263317952.1263324066.24; __utmz=132823709.1262105426.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=96391967.491576186.1262106792.1263028761.1263038127.6; __utmz=96391967.1262106792.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _csuid=X4b47279d2bd1b895; nette-browser=0.900447536123; __utmc=132823709; __utmc=96391967; __utmb=132823709.7.10.1263324066
Content-Type: application/x-www-form-urlencoded
Content-Length: 96
username=tes&password=test&login=P%C5%99ihl%C3%A1sit+se&_token_=d36445451cb8374757d9717da70da07e

HTTP/1.x 200 OK

Editoval gmvasek (12. 1. 2010 20:48)

Aurielle
Člen | 1281
+
0
-

Ještě jedna věc – po nahrání dev verze Nette mám toto:

[2010-01-12 20:41:20] exception 'FatalErrorException' with message 'Call to undefined function callback()' in /mnt/data/accounts/r/runescapewiki/data/www/rswcz/libs/Nette/loader.php:4292
Stack trace:
#0 [internal function]: Debug::_shutdownHandler()
#1 {main}

Editoval gmvasek (12. 1. 2010 21:43)

Ondřej Mirtes
Člen | 1536
+
0
-

Zkus nahrát znova, smaž tempy… Funkce callback přibyla dneska :)

Aurielle
Člen | 1281
+
0
-

K mému problému: zatím jsem ho s hostingem nevyřešil, ale můžete se podívat na historii konverzace od supportu a kouknout na uvedený log, já v něm nic závadného nevidím, případně mi poradit další kroky.

Díky!

Aurielle
Člen | 1281
+
0
-

Na problém se mi podíval jeden z administrátorů Savany a tvrdí, že problém je prý v redirectu. Historie komunikace k nahlédnutí zde.

David Grudl
Nette Core | 8228
+
0
-

Nedala by se ta chyba postupně izolovat, tj. redukovat na nejmenší možný kód, který chybu vyvolá?

Aurielle
Člen | 1281
+
0
-

Zkusím to, až budu mít čas (během zítřka), ale nezdá se mi, že by v 0.9.3 RC byla chyba v redirectu…

Aurielle
Člen | 1281
+
0
-

David Grudl napsal(a):

Nedala by se ta chyba postupně izolovat, tj. redukovat na nejmenší možný kód, který chybu vyvolá?

http://nettetest.runescapewiki.cz
Tady je to k otestování, jedná se o nemodifikovaný příklad CD-collection z examples z 0.9.3 RC balíku.