Dva dotazy k CD-collection
- warp
- Člen | 26
snazim se predelat prihlasovaci script z CD-collection do sveho projektu a zatim v podstate uspesne, jen by me zajimaly dva detaily:
1/ jaka komponenta se stara o vypisovani chyby (spatne zadane heslo, spatne
zadane jmeno) primo na stranku. AuthPresenter
a template
Auth/default.phtml
jsem skopiroval beze zmeny a chyby mi to stale
vypisuje do Ladicky :/
2/ jake kodovani pouziva Nette password, nebo spis dibi. Zkousel jsem klasicke kodovani z html formularu i plain text a ani jedno mi to nevzalo. A pripadne jestli je tu nekde skript pro registraci a tim padem i kodovani hesla rovnou do databaze :)
- warp
- Člen | 26
tak ten prvni problem se mi uz podarilo vyresit, ale s tim kodovanim furt tapu, heslo pri registraci zapisuju do databaze pomoci tohodle kodu:
$heslo = hash('sha256', $form['password']->getValue());
a kdyz ho pak chci vytahnout zpatky pres klasickej password formular
$form->addPassword('password', 'Heslo:')
tak mi nahlasi spatne heslo :-/
- warp
- Člen | 26
puvodne jsem tam mel toto:
$user->login($form['username']->getValue(), $form['password']->getValue());
nahradil jsem to timto:
$pass = (hash('sha256',$form['password']->getValue()));
$user->login($form['username']->getValue(), $pass);
a hlasi to invalid password v obou pripadech
- warp
- Člen | 26
Mam model Users, ale nejak sem tam vubec nenasel propojeni s tim AuthPresenterem, tak sem dam vsechen kod, kterej se tyka prihlasovani a registrace a budu doufat, ze nekdo bude ochotnej se na to mrknout :)
BasePresenter (jedine co se tyka prihlasovani)
$this->getSession()->start();
$user = $this->getUser();
$this->template->user = $user->isLoggedIn() ? $user->getIdentity() : NULL;
AuthPresenter
class AuthPresenter extends BasePresenter
{
public $backlink = '';
protected function createComponentLoginForm()
{
$form = new NAppForm;
$form->addGroup('Přihlašovací formulář');
$form->addText('username', 'Jméno:')
->addRule(NForm::FILLED, 'Nezadal jste jméno.');
$form->addPassword('password', 'Heslo:')
->addRule(NForm::FILLED, 'Nezadal jste heslo.');
$form->addSubmit('login', 'Přihlásit');
$form->addProtection('Please submit this form again (security token has expired).');
$form->onSubmit[] = callback($this, 'loginFormSubmitted');
return $form;
}
public function loginFormSubmitted($form)
{
try {
$user = $this->getUser();
$user->login($form['username']->getValue(), $form['password']->getValue());
$this->getApplication()->restoreRequest($this->backlink);
$this->redirect('Login:');
} catch (NAuthenticationException $e) {
$form->addError($e->getMessage());
}
}
}
model Users
class Users extends NObject implements IAuthenticator
{
public function authenticate(array $credentials)
{
$username = strtolower($credentials[self::USERNAME]);
$password = strtolower($credentials[self::PASSWORD]);
$row = dibi::select('*')->from('uzivatel')->where('Login=%s', $username)->fetch();
if (!$row) {
throw new NAuthenticationException("User '$username' not found.", self::IDENTITY_NOT_FOUND);
}
if ($row->password !== $password) {
throw new NAuthenticationException("Invalid password.", self::INVALID_CREDENTIAL);
}
unset($row->password);
return new NIdentity($row->username, NULL, $row);
}
}
a ted ta cast, ktera se tyka registrovani: RegisterPresenter
class RegisterPresenter extends BasePresenter
{
protected function createComponentFormPassword() {
$form = new NAppForm;
$form->addGroup('Založení nového uživatele');
$form->addText('username', 'Jméno:')
->addRule(NForm::FILLED, 'Zadejte jméno.');
$form->addPassword('password', 'Heslo:')
->addRule(NForm::FILLED, 'Zadejte heslo');
$form->addPassword('password2', 'Heslo (ověření):')
->addRule(NForm::FILLED, 'Zadejte nové heslo ještě jednou, pro kontrolu.')
->addRule(NForm::EQUAL, 'Zadané hesla se neshodují', $form['password']);
$form->addSubmit('submitted', 'Odeslat');
$form->onSubmit[] = array($this, 'formPasswordSubmitted');
return $form;
}
public function formPasswordSubmitted($form) {
$jmeno = $form['username']->getValue();
$heslo = hash('sha256', $form['password']->getValue());
return dibi::query("INSERT INTO [uzivatel] (Login, Heslo, Prava) VALUES ('$jmeno', '$heslo', 0)");
}
}
ale jak rikam, kdyz jsem tam zkusil jako vychozi databazi nastavit ten prilozenej soubor demo.db tak vsechny tyhle procedury probehly uspesne, takze musi byt chyba v hashovani toho hesla v RegisterPresenteru.
Editoval warp (18. 11. 2010 10:39)
- Lopata
- Člen | 139
Při registraci ukládáš do db hash hesla a při loginu s tím hashem porovnáváš normální heslo, co ti user napsal. Takhle to tedy bude fungovat jen pokud ti uživatel napíše hash vlastního hesla.
Databázové operace nedělej v presenteru. Ty volání strtolower jsou podle mě kontraproduktivní. Při registraci neověřuješ, jestli uživatel se zadaným username již neexistuje.
EDIT: too late
Editoval Lopata (18. 11. 2010 11:33)
- warp
- Člen | 26
Bohuzel to stale nefunguje. Zkousel jsem do toho formulare hodit i zahashovane heslo (ctrl c z db) a neproslo to. Podle me ten password label ma nejaky svuj hash kod, ktery neodpovida tomu sha256.
Navic, kdyz sem nahradil kod podle rady, tak se mi ani ze souboru demo.db prihlasit neslo.
Podle vasi teorie by v pripade ze bych ten hash vypustil ve vsech krocich (register i autheticate), tak by to fungovalo a tak to neni.
A o bezpecnost (dat SQL mimo presenter) se muzu starat az mi bude fungovat tenhle zaklad. To same s kontrolou jmen jiz existujicich uzivatelu.
//jeste by mohla byt nejaka zrada v config.ini protoze ten menim pro pristup k souboru / do databaze, ale mam defaultni nastaveni, takze o tom pochybuju
Editoval warp (18. 11. 2010 13:28)
- pekelnik
- Člen | 462
Kristepane!!!
blábol za blábolem – nechápu jak na to někdo může mít nervy… jenom slovo „kódování“ je tazatelem užíváno asi v deseti významech…
- …ake kodovani pouziva Nette password… co to je?
- …klasicke kodovani z html formularu… ano, ano ;)
- …ale s tim kodovanim furt tapu… já taky ;)
- …problem nekde v tom kodovani… zajisté ;)
- …s kodovanim by nemal byt problem… to ne no ;)
„Bohuzel to stale nefunguje.“
Není se čemu divit!
Když tazatel místo aby se zamyslel a třeba si nakreslil na papír co se vlastně v tom programu děje, neustále klade přiblbé dotazy typu: „Zkopírovaný kód nefunguje. Nevíte co je tam za kódování?“
Víme: UTF-8 :D
No a na závěr bych snad jen doporučil používat více funkci
Debug::barDump()
, která přehledně v jakémkoli
místě programu vypíše proměné do debug baru… Dvě proměnné se tak
porovnají neporovnatelně lépe než dotazem do fóra ;)
Editoval pekelnik (18. 11. 2010 14:28)
- warp
- Člen | 26
uz sem nasel kde je zakopanej pes, ale je to tak trapny, ze to snad ani radsi vedet nechcete :D
Pekelnik: tobe se zrejme nikdy nestalo, ze si hledal chybu v programu a pak si ji po nekolikahodinovem hledani nasel v preklepu. dej si nohy do tepla a bude dobre ;)
vsem ostatnim dik za rady, diky takovemu feedbacku je pro me mnohem lehci pochopit Nette jako takovy ;)
Editoval warp (18. 11. 2010 14:37)
- Ped
- Člen | 64
tipuji ze bud nemel v DB dostatecne dlouhy string a se mu to osekalo, nebo mel preklep v nazvu hash funkce a pouzival 2 ruzne.
warp: jeste by bylo dobre pridat ke heslu pred hashovanim „salt“, jinak kdokoli kdo ma predpripravene rainbow tables pro sha256 ti vytaha hesla z te DB po jejim ukradeni lusknutim prstu. Kdyz delas salt, tak by musel ukradnout DB + zdrojak aby vubec salt znal, a i se znalosti saltu jsou mu rainbow tables myslim naprd pokud se nemylim. Bez znalosti saltu jsou mu na prd urcite.
T.j.
$hash = sha256( 'Ped dava salt i pred'.$user_password.'a i po.. a delsi' );
- Ped
- Člen | 64
uz sme si zabehali tak jako tak docela dost… :)
Ale tak trochu joggingu neuskodi… :D
Ale kdyz uz sme u te validace hesel .. kdo to ma udelane poradne vcetne JS
hashovani na client strane + challenge-response ochrany, tak aby to bylo odolne
i proti odposlouchavani pres http:// ?
Ja delam jenom server-side salt+hash, aby ukradena DB byla k nicemu, na
klient-side jsem jeste nemel cas se podivat. Treba jednou…
- jansfabik
- Člen | 193
Doporučuju nastudovat si HMAC, je tam i vzorové řešení pro Javascript a odkaz na PHP funkci hash_hmac. Při odeslání formuláře vezmeš heslo z políčka formuláře, pomocí klíče ho zahashuješ a uložíš do hidden pole. Potom smažeš původní heslo v textovém poli. Je to asi nejbezpečnější varianta, když nemáš k dispozici SSL, protože při každé relaci je klíč jiný, takže pokud útočník odposlechne hash hesla, nemá šanci se s ním ani přihlásit.