Při zachycení vyjímky – bílá obrazovka
- grogy
- Člen | 147
Zdravím,
mám tu menší problém (trošku záhadu) při autentizačním formuláři. Při vyplnění a odeslání sprvných údajů funguje, v opačném případě (falešná přihlašovací data) se zobrazí jen bílá obrazovka. Proto myslím, že to bude chyba při zachycení výjimky. Ovšem nevím jak ji vyřešit.
<?php
....
// Takto vypadá metoda pro vytvoření a zpracování formuláře
public function loginForm()
{
$form = new Form();
$form->setMethod("post");
$form->addText("login", "Uživatelské jméno:", 40)
->addRule(Form::FILLED, "Prosím vyplňte login");
$form->addPassword("pass", "Uživatelské heslo:", 40)
->addRule(Form::FILLED, "Prosím vyplňte heslo");
$form->addImage("odeslat", "/imagesAdmin/button-login.jpg", "Přihlásit se");
if ($form->isSubmitted()) {
$user = Environment::getUser();
// registrace authenzizacniho handleru
require MODELS_DIR . '/Authenticator.php';
$user->setAuthenticationHandler(new Authenticator);
// nastaveni expirace (po 30 min neaktivity nebo vypnuti prohlizece)
$user->setExpiration('+ 30 minutes');
try {
// vlozeni loginu a hesla do handleru
$user->authenticate($form['login']->getValue(), $form['pass']->getValue());
//$this->getApplication()->restoreRequest($this->backlink);
$this->redirect(':Administrace:Default:');
// až sem to funguje OK, při vyjímce která se tu má zachytit, nastane chyba => bílá obrazovka (v Opeře: Připojení bylo ukončeno vzdáleným serverem)
} catch (AuthenticationException $e) {
$form->addError($e->getMessage());
}
}
return $form;
}
....
?>
Autentizační handler je v pořádku, (prakticky to samé co v manuálu či akrabat exemple).
- Honza Kuchař
- Člen | 1662
Zkus tam dát (na vyzkoušení)
} catch (Exception $e) {
$form->addError($e->getMessage());
}
P.S.: Proč nepoužíváš AppForm?
- grogy
- Člen | 147
Nepomohlo to, jen se při správných údajích zobrazí error hláška: Zpráva nebyla odeslána:
Ještě jsem zapomněl zmínit, že laděnka nalogne (do souboru) žádnou chybu.
AppForm jsem nepoužil kvůli chybové hlášce laděnky: „Component is not attached to ‚Presenter‘.“, která odkazuje na řádek:
<?php
if ($form->isSubmitted()) {
?>
tak mám za to, že při tomto ručním zpracování má být použita jen Form. (ale to je jen moje domněnka.)
- Ondřej Mirtes
- Člen | 1536
Tu chybovou hlášku dostáváš, protože takto se s AppFormem nepracuje. Ten v továrničce pouze vytváříš a pro jeho zpracování v případě validního odeslání slouží událost. Takže nějak takto:
protected function createComponentLoginForm() {
$form = new AppForm;
$form->addText("login", "Uživatelské jméno:", 40)
->addRule(Form::FILLED, "Prosím vyplňte login");
$form->addPassword("pass", "Uživatelské heslo:", 40)
->addRule(Form::FILLED, "Prosím vyplňte heslo");
//$form->addImage("odeslat", "/imagesAdmin/button-login.jpg", "Přihlásit se");
$form->onSubmit[] = array($this, 'loginFormSubmitted');
$form->addSubmit('okSubmit', 'Přihlásit se');
return $form;
}
public function loginFormSubmitted(AppForm $form) {
Debug::dump($form->getValues());
//zpracování přihlášení
}
Do šablony ho dostaneš v nějaké render metodě pomocí
$this->template->form = $this->getComponent('loginForm');
a nebo bez jakéhokoli přiřazování přímo v šabloně napsáním
{control loginForm}
.
Editoval LastHunter (10. 8. 2009 20:59)
- grogy
- Člen | 147
Ok, to mi tedy nějak uniklo (hlavně $this->getComponent(‚loginForm‘); s tím že v klidu můžu použít továrničky.
- Je tedy v praxi k něčemu přímo třída Form?
- Stejně to neřeší můj problém (ikdyž toto je asi lepším řešením), tak problém s bílou obrazovkou přetrvává. To že továrničku „tahám“ pomocí $this->getComponent(‚loginForm‘); v action nemá vliv?
(Zkoušel jsem Nette Framework Requirements Checker, jen 3 warningy (Memcache extension, ImageMagick library a Fileinfo extension or function mime_content_type) – ty by podle mě neměli mít vliv.)
- grogy
- Člen | 147
Zasílám ještě autentizační handler, ale ten by měl být v pořádku:
<?php
// BaseModel jako rodic resi pripojeni k databazi apd, je deden od Object
require_once 'BaseModel.php';
class Authenticator extends BaseModel implements IAuthenticator
{
public function authenticate(array $credentials)
{
$username = $credentials[self::USERNAME];
$password = sha1($credentials[self::PASSWORD] . md5($credentials[self::USERNAME])); // tvorba hashe
// hledani zaznamu o uzivateli
$row = parent::$db->select("*")->from("uzivatele")->where("login = %s", $username)->fetch();
if (!$row) { // nenalezeni uzivatele
throw new AuthenticationException("Špatné přihlašovací údaje, zkuste to prosím znovu.", self::IDENTITY_NOT_FOUND);
}
if ($row->heslo !== $password) { // neshoda hesel
throw new AuthenticationException("Špatné přihlašovací údaje, zkuste to prosím znovu.", self::INVALID_CREDENTIAL);
}
return new Identity($row->jmeno . " " . $row->prijmeni); // vraceni identity
}
}
?>
- PetrP
- Člen | 587
grogy napsal(a):
Ok, to mi tedy nějak uniklo (hlavně $this->getComponent(‚loginForm‘); s tím že v klidu můžu použít továrničky.
- Je tedy v praxi k něčemu přímo třída Form?
- Stejně to neřeší můj problém (ikdyž toto je asi lepším řešením), tak problém s bílou obrazovkou přetrvává. To že továrničku „tahám“ pomocí $this->getComponent(‚loginForm‘); v action nemá vliv?
(Zkoušel jsem Nette Framework Requirements Checker, jen 3 warningy (Memcache extension, ImageMagick library a Fileinfo extension or function mime_content_type) – ty by podle mě neměli mít vliv.)
- Je pro použití mimo Nette\Application. Jde použít i tam, ale AppForm je pro to vhodnější (musíš ho ale připojit k presenteru)
- nemělo by mít vliv kde a kdy ho voláš, pokud tam na něm ještě nedéláš nějaké šílenosti ;]
Jinak problém bych možná vyděl v špatném nastavení laděnky, (a tedy
že chyba bude někde uplně jinde)
skus
Debug::enable(false);
Environment::getApplication()->catchException = false;
Také by mě zajímalo kde se bere zpráva:
Zpráva nebyla odeslána
- grogy
- Člen | 147
Tímto zapnu Laděnku na 100% že?
Dal jsem to tam, zkusil jsem i nahrát novou hnihovnu (mini i full verzi),
a stále je výsledek stejný.
Componentu si volám takto, to se mi zdá v pořádku:
<?php
public function renderPrihlaseni()
{
$this->template->title = "Přihlašování";
$this->setLayout('layoutAdminLogin');
$this->template->form = $this->getComponent('loginForm');
}
?>
- grogy
- Člen | 147
Zkusil jsem to celé překopat, napsat úplně od znova pomocí dokumentace, fóra a exemplu. Bohužel výsledek nulový. Pastnu celé kódy na server, pokud budete mít někdo čas se na to podívat a zkusit najít tu neuvěřitelnou blbost co je někde schovaná budu vděčný:
Presenter (BasePresenter je teď prázdný)
View (pro jistotu taky přikládám)
BaseModel (pro jistotu)
Doufám, že nevadí odkazování na jiný server – nechtěl jsem tím „zaprasit“ několik stránek fóra.
Můj problém tedy ještě jedno: Po zadání špatných přihlašovacích údajů se zobrazí jen bílá stránka. I při zapnuté laděnce se nic nezobrazí, ani nelogne. Jinak je to celé OK.
Ikdyž authentizace s Nette vypadá celkem jako triviální záležitost, tak koukám jak mi slušně zavařila..
- PetrP
- Člen | 587
Co ta zpráva Zpráva nebyla odeslána
, víš od kud se
bere?
A jakou verzi/revizi nette používás?
Na první pohled nevydím žadnou chyby, zítra v práci až budu mít chvilku tak se v tom poštourám.
Jinak chyba je pořád bílá stránka? Nepomuže postupné krokování? Třeba že bysis zakomentovával různý části a zistil na čem to spadne.
Ještě napis verzi PHP a co říká Requirements Checker
- grogy
- Člen | 147
Checker jsem uváděl výše – (Zkoušel jsem Nette Framework Requirements Checker, jen 3 warningy (Memcache extension, ImageMagick library a Fileinfo extension or function mime_content_type) – ty by podle mě neměli mít vliv.)
Revizi teď nejnovější (0.9 (revision 480 released on 2009/08/12 05:09:07)), včera nějaká o 2–3 čísla menší (ovšem pořád to samé). Zkoušel jsem tam i plnou verzi (jinak tam byla jen minified verze). To všechno jsem zkoušel. S Nette začínám, ale stabilní 0.8 by také měla jet – že? Zkusím rovnou.
Verze PHP je PHP 5.2.9-pl2-gentoo. – Hosting Savana, to by podle mě také neměl být problém.
To pmg: xD
- Ondřej Mirtes
- Člen | 1536
Mrkni se do Firebugu, jestli je v HTTP hlavičce vůbec uvedený Nette Framework. Jinak bude problém v nějaké vyší moci (aka Apache a mod_rewrite?)
- grogy
- Člen | 147
Takže, buďto mám halušky, nebo už fakt nevim..
Hlavičky (bílé stránky) vypadají takto:
Date: Thu, 13 Aug 2009 22:18:26 GMT
Server: Apache
X-Powered-By: Nette Framework
Content-Length: 2198
Keep-Alive: timeout=2, max=30
Connection: Keep-Alive
Content-Type: text/html
200 OK
Ovšem – při zobrazení té samé stránky v Opeře vyjede hláška: „Připojení bylo ukončeno vzdáleným serverem“
- Verze Apache a mod_rewrite jsem zatím nevyšetl.
Editoval grogy (14. 8. 2009 0:13)
- grogy
- Člen | 147
Ještě mě napadlo zobrazit componentu pomocí widgety v pohledu – logicky by to mělo být stejné, ovšem z Laděnky vyskočilo toto:
Call to a member function getErrors() on a non-object – zkusil jsem zkopírovat komponentu se spracováním z exemlu (přesně vše kolem komponety jsem jen zkopnul do mé aplikace) a to samé.
- grogy
- Člen | 147
Další dny zkoušení a nic. Byl bych raději kdyby mě někdo kopnul do ***, že tam mám nějakou blbost, ale tohle mi už leze na mozek – podlě mě správný kód a nefunguje, hosting Savana, který tu používá více lidí, zkoušena na více PC a také nic. :( Zkusil jsem i dnešní revizi a nic.
Zkusil jsem to ještě odbugovat, zakomentoval jsem jednotlivé části a dělá to opravdu jen u toho zachycení výjimky z autentizačního handleru. Vše ostatní jinak chodí přesně jak má. Nemůže to být tím že to je v modulu (což je blbost?).
- grogy
- Člen | 147
Mé trošku starší vlákno – kde problém jsem odložil, ale teď jej musím akutně vyřešit.
Chyba je popsána výše – jedná se stále o to, že při přihlašování (uděláno z exemple) se při nesprávných údajích zobrazí jen bílá obrazovka (na FF, na ostatních browserech se zobrazí hláška o nedostupnosti stránky).
Při pokusu o odbugování jsem zjistil, že je to jen při zachycení vyjímky. Ve zpracování nepomohlo ani přepsání na catch (Exception $e). https://doc.nette.org/…ubleshooting nepomohlo, logování chyb je zaplé, ovšem log prázdný.
Nette stable 0.9.1 (revision dc607f0 released on 2009–09–18), PHP 5.2.9-pl2-gentoo, Requirements Checker proběhl úspěšně.
- HonzaMac
- Člen | 40
Přidávám se ke stejné nefunkčnosti.
U mě jsem zjistil následující:
Zkončí to při vyvolávání vyjímky.
Ale když zapnu Debug::enable(Debug::DEVELOPMENT);
tak to funguje bez problemu v IE8, Opeře, ale ve FF stále stejné. Ani
restart prohlížeče nepomohl.
Když vypnu debug, tak to nejede ani v jednom.
Nějaké nápady? Přihlašování je podle vzorového, které je zde několikrát kopírováno znova a znova.
Děkuji
- Ondřej Mirtes
- Člen | 1536
Zkus ještě v bootstrapu
$application->catchExceptions = false
;
Requirements checker jsi zkoušel?
- HonzaMac
- Člen | 40
Ani jedno nepomohlo.
Jak jsem psal, funguje to castecne jenom pri zaplem development … jinak to
nefunguje jinde
Checker je bez problemu.
Hosting savana.cz.
Asi budu zkoumat vnitrnosti nette
Hlavička požadavku:
Host: iis.fineboard.cz
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; cs; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 (.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,en-us;q=0.7,en;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://iis.fineboard.cz/cs/auth/login/?backlink=f1a7
Cookie: nette-browser=0.947623085448; PHPSESSID=442b7289f2049d5cc94fe8dc7da3e882; netteProfilerVisible=1; netteProfilerPosition=1px:0px
Možná by tam měl být i Location: ne?
- grogy
- Člen | 147
Bohužel, stále nevím co s tím. Možný je i ten problém v Apachi.
Zkoušel jsem oficiální „CD-collection“ z examples a pořád to samé. Checker, jak píše HonzaMac, tak je stále v pořádku. Hosting SAVANA.
Máte někdo řešení jak to obejít? Rád bych pracoval s Identity (kdo je přihlášen, jaká má práva), jelikož je to dobře zakomponované v celém Nette.
- HonzaMac
- Člen | 40
Napadlo mě, že by se mohlo hodit phpinfo ze Savany.cz
Možná by se chtělo podívat do logu na apachi … ale to se mi asi jen tak nepodaří :-(
Editoval HonzaMac (18. 11. 2009 10:26)
- David Grudl
- Nette Core | 8218
xcache neznám, ale předpokládám, že to je potřeba vypnout dříve než v PHP, tedy na úrovni .htaccess nebo vyšší. Možná napsat na hosting. Protože je tohle velmi specifická chyba, je nejlepší eliminovat všechny možné nestandardní vlivy a jedním z nich může být i xcache.
- medvedobijec
- Člen | 11
Zdravím, narazil jsem na stejný problém, jaký se zde řeší. Hosting taktéž Savana. Povedlo se najít někomu řešení?
- Cifro
- Člen | 245
https://forum.nette.org/…hostu-vse-ok?…
Debug::enable(false)
$application->catchExceptions = false;
zobrazí ti laděnku.
Editoval Cifro (7. 1. 2010 23:11)
- iguana007
- Člen | 970
Ja bych si napsal na podporu o dump logu z Apache – pokud je to seriozni hosting, meli by ti vyjit vstric. Btw. je trosku divne, ze nemas pristup k logum.
Ja mel taky divnou zahadu vcera vecer – me pro zmenu Nette shazovalo Apache. Chybu jsem hledal asi hodinu a nic nenasel, pak zkusil restart kompu a uz to bezelo jak ma, aniz bych zmenil jedinou radku v aplikaci.
Drzim palce, snad v logu neco najdes …
igi
- David Grudl
- Nette Core | 8218
Když se dívám na to phpinfo, tak je tam několik dodatečných modulů:
- XCache v1.2.2 z roku 2007
- ionCube PHP Loader v3.1.33 z roku 2007
- Zend Optimizer v3.3.3 z roku 2007
- spectator
- a PHP 5.2.9 z roku 2009
Na 99 % bude problém v těch doplňujících modulech. Takže by to chtělo požádat adminy, aby je v rámci nalezení chyby vypnuli (např. postupně) a případně updatovali na aktuální verze. Vůbec použití tří opcode keší vypadá docela crazy, ale třeba to spolu může fungovat dobře, nevím.
- Aurielle
- Člen | 1281
Podařilo se mi vymyslet šílený walkaround, ale nechtěl bych to takto v aplikaci nechat. Podotýkám, že je to hodně prasácký způsob…
Authenticator:
/**
* Bugfix for Savana production server
*
* @author Gmvasek
* @copyright Copyright (c) 2009, 2010 Gmvasek
* @package RuneScapeWiki
*/
class SavanaAuthenticator extends RSWAuthenticator
{
const BAD_PASSWORD = 5;
const USER_INACTIVE = 6;
const USER_BANNED = 7;
/**
* 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))
{
return new FailedIdentity(self::INVALID_CREDENTIAL);
}
// Get user by username
try
{
$userdata = RSWUser::get($username, RSWUser::USERNAME);
}
catch(UserNotFoundException $e)
{
return new FailedIdentity(self::IDENTITY_NOT_FOUND);
}
// Hash the password and compare it
$password = RSWUser::createHash($password, $salt);
if($password !== $userdata->user_password)
{
return new FailedIdentity(self::BAD_PASSWORD);
}
// User is inactive...
if(self::INACTIVE === (int) $userdata->user_active)
{
return new FailedIdentity(self::USER_INACTIVE);
}
// or banned...
if(self::BANNED === (int) $userdata->user_active)
{
return new FailedIdentity(self::USER_BANNED);
}
// Assign role
$role = $role[$userdata->user_type];
// Return identity
return new Identity($userdata->username, $role, $userdata);
}
}
FailedIdentity:
/**
* Error identity implementation, bugfix
*
* @author Gmvasek
* @copyright Copyright (c) 2009, 2010 Gmvasek
* @package RuneScapeWiki
*/
class FailedIdentity extends FreezableObject implements IIdentity
{
public $code;
public function __construct($code)
{
$this->code = (int) $code;
if($code === SavanaAuthenticator::USER_BANNED)
{
Environment::getApplication()->getPresenter()->flashMessage('Tento uživatelský účet byl zabanován administrátorem RuneScape Wiki. Není možné se na něj přihlásit.', 'error');
}
else if($code === SavanaAuthenticator::USER_INACTIVE)
{
Environment::getApplication()->getPresenter()->flashMessage('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.', 'warning');
}
else if($code === SavanaAuthenticator::INVALID_CREDENTIAL)
{
Environment::getApplication()->getPresenter()->flashMessage('Jméno nebo heslo nemůže být prázdné.', 'warning');
}
else if($code === SavanaAuthenticator::IDENTITY_NOT_FOUND)
{
Environment::getApplication()->getPresenter()->flashMessage('Zadaný uživatel neexistuje.', 'warning');
}
else if($code === SavanaAuthenticator::BAD_PASSWORD)
{
Environment::getApplication()->getPresenter()->flashMessage('Bylo zadáno špatné heslo.', 'warning');
}
else
{
Environment::getApplication()->getPresenter()->flashMessage('Nastala chyba, zkuste formulář odeslat znovu.', 'warning');
}
}
public function getCode()
{
return $this->code;
}
public function getName()
{
}
/** @compatibility for dev Nette version */
public function getId()
{
}
public function getRoles()
{
}
}
A konečně fixnutý kód v UserPresenteru:
// Bugfixed code for Savana production server using SavanaAuthenticator
$user->authenticate($values['username'], $values['password']);
$identity = $user->getIdentity();
if($identity instanceof FailedIdentity)
{
$user->signOut(TRUE);
$this->redirect(303, 'User:login');
}
Editoval gmvasek (24. 1. 2010 9:17)
- lucass
- Člen | 89
Zdar,
děje se u mě to samé, tj. při zachycení výjimky detekující špatné uživ. jméno nebo heslo se místo chybových flashMessages zobrazí bílá stránka. Hosting není Savana, ale vlastní. Na localu (Vista) to funguje, na serveru (Linux) ne. Debug i Environment mám nastavený na DEVELOPMENT, laděnku zapnutou.
Přihlašovací formulář má signál LoginClicked, v něm následující kód:
<?php
...
public function LoginClicked($form) {
$data = $this->getValues();
$user = Environment::getUser();
$user->setAuthenticationHandler(new UserAuthenticator);
try {
$user->authenticate($data['username'], $data['password']);
$user->setExpiration('+ 30 minutes');
$this->presenter->flashMessage(sprintf('Byl jste přihlášen jako %s.', $data['username']), IFlash::SUCCESS);
$this->presenter->redirect('this');
} catch (AuthenticationException $e) {
$this->presenter->flashMessage('Přihlášení se nezdařilo.', IFlash::ERROR);
$this->presenter->flashMessage(sprintf('Důvod chyby: %s'), $e->getMessage()), IFlash::ERROR);
}
}
...
?>
FireBug hlásí 200 OK, v záložce Odezva je prázdno a Request_Count 0. Zkoušel jsem v odchycení toto:
<?php
...
} catch (AuthenticationException $e) {
$this->presenter->redirect('this'); // nezalezi, jestli this nebo jina destinace
}
...
?>
Ale stránka je stále bílá, k přesměrování nedojde. Nemůže být nějaký konflikt v životním cyklu formuláře (AppFormu)? Něco, co souvisí s autentizací, popř. s nějakou autodetekcí productionMode, přestože nastavuji developmentMode a Debug::$productionMode hlásí FALSE.
Zkoušel jsem i try-catch vypnout, jestli mi laděnka vyhodí nějakou rozumně formulovanou hlášku, ale problém stejný.
Log Apache je také prázdný:/
Napadá někoho, jak dál?
EDIT: Ještě doplním, že FF bílá stránka, ale IE8 hlásí „Aplikace Internet Explorer nemůže zobrazit tuto webovou stránku.“
Editoval lucass (9. 2. 2010 17:33)
- Ondřej Mirtes
- Člen | 1536
Prohodil bych setExpiration a authenticate. A do catch bloku bych místo
těch flash zpráviček dal $form->addError('hláška')
, to ti
stránka zůstane správně na té aktuální a s předvyplněnými
hodnotami.
Ještě bych smazal řádek s
$user->setAuthenticationHandler(new UserAuthenticator);
a do
configu dal toto:
service.Nette-Security-IAuthenticator = UserAuthenticator
Takhle to mám já a nikdy jsem neměl problém :) Tak dej vědět, jestli to náhodou nepomůže.