Overenie Username a Emailu či už existujú v Db ANEB Pokus o registráciu!
- SontoEremo
- Člen | 341
Zdravím…
Takže som dal ako tak dokopy registráciu užívateľa vychádzal som
s examples CD-Collection!
prosím všetkých kompetentných o kontrolu a čo by som mal tak asi
zmeniť…
Ako mne to podstatne funguje ale tak človek si nie je na 100% istí
Takže môj UserRepository
<?php
class UserRepository extends Nette\Object
{
/** @var Nette\Database\Connection */
private $database;
public function __construct(Nette\Database\Connection $database)
{
$this->database = $database;
}
public function findAll()
{
return $this->database->table('users');
}
public function findById($uid)
{
return $this->findAll()->get($uid);
}
public function insert($values)
{
return $this->findAll()->insert($values);
}
public function userexists($uname)
{
return $this->findAll()->select('uname')->where('uname', $_POST['uname'])->fetch();
if($this->users->userexists('uname'))
{
echo 'Existuje';
} else {
echo 'Je Voľné';
}
return $this->users->userexists($uname);
}
public function usermailexists($umail)
{
return $this->findAll()->select('umail')->where('umail', $_POST['umail'])->fetch();
if($this->users->userexists('umail'))
{
echo 'Existuje';
} else {
echo 'Je Voľné';
}
return $this->users->usermailexists($umail);
}
}
Môj UserPresenter
<?php
namespace FrontModule;
use Nette\Application\Ui\Form,
Nette\Utils\Html,
Country,
DatePicker,
UserRepository;
class UserPresenter extends \BasePresenter
{
/** @var UserRepository */
private $users;
public function inject(UserRepository $users)
{
$this->users = $users;
}
protected function createComponentUserRegisterForm()
{
$form = new Form;
$form->addText('uname', 'Užívateľské meno:')
->setRequired('Prezývka je povinná!');
$form->addText('umail', 'Emailová adresa:')
->setRequired('Email je povinný!')
->addRule(Form::EMAIL, 'Zadajte prosím, platnú emailovú adresu!');
$form->addPassword('upass', 'Heslo:')
->setRequired('Heslo je povinné!')
->addRule(Form::MIN_LENGTH, 'Heslo musí obsahovať min. %d znaky', 4);
$sex = array('m' => 'Muž','f' => 'Žena',);
$form->addRadioList('ugender', 'Pohlavie:', $sex)
->setRequired()
->getSeparatorPrototype()->setName(NULL);
$form->addDatePicker('birthDate', 'Dátum Narodenia:')
->setAttribute('class', 'birthDate')
->addRule(Form::VALID, 'Entered birth date is not valid!');
$ucountries = $this->CountryList();
$prompt = Html::el('option')->setText('Vyberte Krajinu')->class('prompt');
$form->addSelect('ucountry', 'Krajina:', $ucountries)
->setPrompt($prompt)
->setRequired();
$form->addCheckBox('uagree', Html::el('span')
->setHtml('Súhlasím s <a href="../docs/Terms" target="_blank">Podmienkamy</a>')) // Html form
->addRule(Form::EQUAL, 'Musíte súhlasiť s podmienkamy!', TRUE);
$form->addSubmit('uregme', 'Registrovať')
->onClick[] = $this->UserSuccessRegisterSubmitted;
$form->addProtection();
return $form;
}
public function UserSuccessRegisterSubmitted($button)
{
try{
$values = $button->getForm()->getValues();
if($this->users->userexists('uname'))
{
$this->presenter->flashMessage("Užívateľské meno:" . " | " . $_POST['uname'] . " | " . "už Existuje!");
} else {
$this->presenter->flashMessage("Hurá užívateľské meno:" . " | " . $_POST['uname'] . " | " . "je voľné!");
}
/******** @return Email Exists */
if($this->users->usermailexists('umail'))
{
$this->presenter->flashMessage("Emailová adresa:" . " | " . $_POST['umail'] . " | " . "je v systéme zaregistrovaná");
} else {
$this->presenter->flashMessage("Hurá emailová adresa:" . " | " . $_POST['umail'] . " | " . "nie je v systéme zaregistrovaná");
}
} catch(Nette\Security\AuthenticationException $e) {
$form->addError($e->getMessage());
}
}
}
Viem, že som tam veľa veci dokafral preto Vás prosím o upresnenie čo sa týka Nette Dokumentácie,Planette a Fóra stále to študuje ale rád sa púšta do riešenia sám aby som vydel chyby a precvičoval sa no vy ty SKÚSENEJŠÍ to máte v malíčku pre Vás pozrieť na to a ohodnotiť to nie je žiaden problém…
Všetkým samozrejme vopre ďakujem.
Editoval SontoEremo (25. 3. 2013 21:55)
- Draffix
- Člen | 146
A funguje ti to? To je podstatná otázka. Nicméně mám dvě výtky:
- postovací hodnoty bych určitě nebral způsobem $_POST[‚uname‘] z důvodu validace escapování.
- to ověřování emailu a jména v modelu se mi nezdá. Mělo by to být ve smyslu, že pokud existuje záznam, pak vrátím záznam, jinak např. do proměnné uložím že neexistuje. I to bych ale přesunul do presenteru, protože zde by měla probíhat aplikační logika a model by měl sloužit jen jako nástroj pro výběr dat v tomto případě.
Metoda serSuccessRegisterSubmitted je totálně špatně. Doporučuji si přečíst dokumentaci o formulářích
- David Matějka
- Moderator | 6445
- jak pise @Draffix, nikdy nesahej na $_POST (ani $_GET) .. (btw. co kdyby je nette unsetnulo? :D)
- nejdriv jsem se lek
public function userexists($uname)
{
return $this->findAll()->select('uname')->where('uname', $_POST['uname'])->fetch();
if($this->users->userexists('uname'))
{
echo 'Existuje';
} else {
echo 'Je Voľné';
}
return $this->users->userexists($uname);
}
ale on je tam hned na prvnim radku return, tak ten zbytek smaz, at nevystrasis nekoho dalsiho :D (to same v usermailexists)
3. proc tam v tom repository sahas na $_POST, kdyz mas ten email/jmeno v parametru?
4. nenavazuj udalost na
$form->addSubmit('uregme', 'Registrovať')
->onClick[] = $this->UserSuccessRegisterSubmitted;
ale na $form->onSuccess[] = ...
5. overeni existence emailu (a jmena) muzes pouzit pres addRule, napr takhle:
$userRepository = $this->userRepository;
$form->addText('email', 'E-mail')->addRule(function($input) use($userRepository) {
return !$userRepository->usermailexists($input->value);
}, 'Tento email jiz nekdo pouziva!');
6. pokud uz budes neco overovat az v onSuccess metode, tak tu chybu
nezobrazuj pres flashMessage, ale pridej ji do
formu $form->addError('....')
7. v presenteru nemusis pouzivat
$this->presenter->flashMessage()
,
staci $this->flashMessage()
- SontoEremo
- Člen | 341
Jaaa to asi vzdám s Nette absolútne tomu nedokážem prísť na rozum :) už sa stým hrám skoro mesiac a ešte som nedokázal vytvoriť ani len obyčajnú registráciu užívateľa dokonca ani login a dokonca ani neviem kam čo mám umiestniť čo kam patrí apod. viem je to na smiech ale fakt sa snažím no aj tu čo mi pred chvíľou odp. matej21
$userRepository = $this->userRepository;
$form->addText('email', 'E-mail')->addRule(function($input) use($userRepository) {
return !$userRepository->usermailexists($input->value);
}, 'Tento email jiz nekdo pouziva!');
Kam to mám umiestniť? neviem tak som to pacol sem:
$form->addText('umail', 'Emailová adresa:') // umail as email
->addRule(function($input) use($userRepository )
{
return !$userRepository->usermailexists($input->value);
}, 'Tento email jiz nekdo pouziva!')
->setRequired('Email je povinný!')
->addRule(Form::EMAIL, 'Zadajte prosím, platnú emailovú adresu!'); input
Alebo aj toto:
6. pokud uz budes neco overovat az v onSuccess metode, tak tu chybu nezobrazuj pres flashMessage, ale pridej ji do formu $form->addError('')
Tak som to dal takto
public function UserSuccessRegisterSubmitted(Form $form)
{
try{
$values = $form->getValues();
$this->users->insert($values);
} catch(Nette\Security\AuthenticationException $e) {
$form->addError($e->getMessage());
return;
}
}
Nič žiadne, že email už existuje proste zapíše do DB a hotovo!
Dokumentáciu,fórum a Planette stále dookola čítam a robím podľa nej
všetko je ok ale akonáhle niečo sám som ako na opustenom ostrove… :)
Ako tu toto fórum číslo 1 nápomocné a ochotné no nebaví
ma sa ustavične pýtať hlúpe veci či to mám dobre ako to a ako hento…
škoda, že nie je viac video tutoriálov napr.
Registrácia/Prihlásenie/Odhlásenie atď…
Možno sa to časom naplní ale fakt už neviem či som vekom osprostel :) alebo
ja neviem, že nedokážem zachytiť pointu tohto skvelého a asi aj
najlepšieho Frameworku…
P.S: Nerobí niekto náhodou za pár € doučovanie v na SK okolie
Nitra?
rád by som sa zaúčal :) FAKT!
- David Matějka
- Moderator | 6445
umisteny je to v podstate dobre, jen to dej jako posledni validacni pravidlo, vyhodnocujou se postupne, takze je zbytecny overovat, zda existuje email, pokud nebyl vyplnen, tedy:
$form->addText('umail', 'Emailová adresa:') // umail as email
->setRequired('Email je povinný!')
->addRule(Form::EMAIL, 'Zadajte prosím, platnú emailovú adresu!')
->addRule(function($input) use($userRepository )
{
return !$userRepository->usermailexists($input->value);
}, 'Tento email jiz nekdo pouziva!');
to ale nevysvetluje, proc dojde k zapisu (zavolani ty metody UserSuccessRegisterSubmitted).. bud je nejaka chyba v modelu (v metode usermailexists) nebo nevim :)
jinak ta metoda pro zpracovani formu staci takhle:
public function UserSuccessRegisterSubmitted(Form $form)
{
$values = $form->getValues();
$this->users->insert($values);
}
ten try-catch blok tam byl jen v login formu, kde metoda
$user->login
mohla vyhodit vyjimku AuthenticationException, coz
se tady stat nemuze
tak se koukni, jestli je dobre napsana ta metoda v modelu a jestli se treba provede odpovidajici sql dotaz.
- jiri.pudil
- Nette Blogger | 1032
Nebylo by lepší mít na příslušném sloupci v DB unikátní klíč? Tak se ti o kontrolu duplicity postará databáze a ty jen ve zpracování zachytíš výjimku s příslušným kódem:
public function UserSuccessRegisterSubmitted(Form $form)
{
try {
$values = $form->getValues();
$this->users->insert($values);
$this->flashMessage(...);
$this->redirect(...);
} catch (\PDOException $e) {
if ($e->getCode() === 23000) {
// pokud je chyba v duplicitě klíče, přidáme chybu do formu
$form->addError(...);
} else {
// pokud jde o jinou chybu, necháme ji probublat výš
throw $e;
}
}
}
Pak se obejdeš bez vlastního validačního pravidla.
- SontoEremo
- Člen | 341
Ďakujem Vám všetkým za odpovede a za pomoc…
Poskladal som to takto dokopy a funguje zatiaľ ako má!
Prosím Vás mohli by ste to prekontrolovať? Vopred Ďakujem…
Môj UserRepository:
Chyba bola v tom, že za ->where(‚umail‘) som mal ešte dosadiť
,$umail asi takto
return $this->findAll()->select('umail')->where('umail', $umail)->fetch();
Keď som to tam dosadil začalo to vyhadzovať tie hlášky a nekonal sa žiadny zápis až som zmenil mail a potom sa pekne zapísalo do DB a zároveň vykonalo aj redirect
<?php
/**
* Tabulka user
*/
class UserRepository extends Nette\Object
{
/** @var Nette\Database\Connection */
private $database;
public function __construct(Nette\Database\Connection $database)
{
$this->database = $database;
}
public function findAll()
{
return $this->database->table('users');
}
public function findById($uid)
{
return $this->findAll()->get($uid);
}
public function insert($values)
{
return $this->findAll()->insert($values);
}
public function userexists($uname)
{
return $this->findAll()->select('uname')->where('uname', $uname)->fetch();
}
public function usermailexists($umail)
{
return $this->findAll()->select('umail')->where('umail', $umail)->fetch();
}
}
Ešte priložím môj UserPresenter
<?php
namespace FrontModule;
use Nette\Application\Ui\Form,
Nette\Utils\Html,
Country,
DatePicker,
UserRepository;
class UserPresenter extends \BasePresenter
{
/** @var UserRepository */
private $users;
public function inject(UserRepository $users)
{
$this->users = $users;
}
protected function createComponentUserRegisterForm()
{
$userRepository = $this->users;
$form = new Form;
$form->addText('uname', 'Užívateľské meno:')
->setRequired('Prezývka je povinná!')
->addRule(function($input) use($userRepository)
{
return !$userRepository->userexists($input->value);
}, 'Toto užívateľské meno je obsadené prosím vyberte si iné!');
$form->addText('umail', 'Emailová adresa:')
->setRequired('Email je povinný!')
->addRule(Form::EMAIL, 'Zadajte prosím, platnú emailovú adresu!')
->addRule(function($input) use($userRepository)
{
return !$userRepository->usermailexists($input->value);
}, 'Táto emailová adresa je už v systéme zaregistrovaná!');
$form->addPassword('upass', 'Heslo:')
->setRequired('Heslo je povinné!')
->addRule(Form::MIN_LENGTH, 'Heslo musí obsahovať min. %d znaky', 4);
$sex = array('m' => 'Muž','f' => 'Žena',);
$form->addRadioList('ugender', 'Pohlavie:', $sex)
->setRequired()
->getSeparatorPrototype()->setName(NULL);
$form->addDatePicker('birthDate', 'Dátum Narodenia:')
->setAttribute('class', 'birthDate')
->addRule(Form::VALID, 'Entered birth date is not valid!');
$ucountries = $this->CountryList();
$prompt = Html::el('option')->setText('Vyberte Krajinu')->class('prompt');
$form->addSelect('ucountry', 'Krajina:', $ucountries)
->setPrompt($prompt)
->setRequired();
$form->addCheckBox('uagree', Html::el('span')
->setHtml('Súhlasím s <a href="../docs/Terms" target="_blank">Podmienkamy</a>'))
->addRule(Form::EQUAL, 'Musíte súhlasiť s podmienkamy!', TRUE);
$form->addSubmit('uregme', 'Registrovať');
$form->onSuccess[] = $this->UserSuccessRegisterSubmitted;
$form->addProtection();
return $form;
}
public function UserSuccessRegisterSubmitted(Form $form)
{
//$values = $form->getValues();
//$this->users->insert($values);
try {
$values = $form->getValues();
$this->users->insert($values);
$this->flashMessage(....);
$this->redirect('Index:index');
} catch (Nette\Security\AuthenticationException $e) {
if ($e->getCode() === 23000) {
// pokud je chyba v duplicitě klíče, přidáme chybu do formu
$form->addError(...);
} else {
// pokud jde o jinou chybu, necháme ji probublat výš
throw $e;
}
}
}
}
Tak to s Nette teda skúsim odznova Možno, že o pár mesiacov ba i týždňov sa budem tomu smiať čo som sa tu pýtal a aké chyby som robil … No nejak sa to naučiť človek musí! Ďakujem Chalani…
- jiri.pudil
- Nette Blogger | 1032
Teď to try-catch můžeš vyhodit a nechat ve zpracování jen:
$values = $form->getValues();
$this->users->insert($values);
$this->flashMessage(....);
$this->redirect('Index:index');
protože duplicitu si ověřuješ sám.
- SontoEremo
- Člen | 341
Ešte som sa chcel spýtať ako riešite pri registrácii zabezpečenie a zahashovanie hesla? v presentery? niečo ako calculateHash ? v Sandboxe?
- Draffix
- Člen | 146
Bezpečnost je kapitola sama o sobě. Nicméně určitě bych to řešil nějakým hashovacím algoritmem, na netu jich najdeš mraky. Jinak opět ze šablony (resp. view) získáš heslo, v presenteru ho zahashuješ podle tebou vybraného kryptu a přes model ho do databáze uložíš. Tedy stejný princip jako máš ty teď, jen přidáš hash navíc. Taková vhodná třída pro ukázku je např. Authenticator, více se o ní dozvíš tady a snad to lépe pochopíš.
- David Matějka
- Moderator | 6445
k ukladani hesel: http://www.michalspacek.cz/…profit-devel
ke kazdymu heslu pouzij jinej salt, pouzi alespon sha256 (nejlepe vsak bcrypt (resp. crypt)), jak je na tech slajdech
- SontoEremo
- Člen | 341
Ešte naposledy obnovím túto tému…
Takže vytvoril som si
PassHash
<?php
use Nette\Utils\Strings;
class PassHash extends Nette\Object
{
public static function passwordHasher($password, $salt = null)
{
if ($salt === null)
{
$salt = '$2a$07$' . Strings::random(22);
}
return crypt($password, $salt);
}
}
A toto mám v UserPresentery
<?php
namespace FrontModule;
use Nette\Application\Ui\Form,
Nette\Utils\Html,
Country,
DatePicker,
UserRepository,
PassHash;
class UserPresenter extends \BasePresenter
{
/** @var UserRepository */
private $users;
/** @var PassHash */
private $salt;
public function inject(UserRepository $users)
{
$this->users = $users;
}
public function injectpasswordHasher(PassHash $salt)
{
$this->salt = $salt;
}
protected function createComponentUserRegisterForm()
{
$userRepository = $this->users;
$form = new Form;
$form->addText('uname', 'Užívateľské meno:')
->setRequired('Prezývka je povinná!')
->addRule(function($input) use($userRepository)
{
return !$userRepository->userexists($input->value);
}, 'Toto užívateľské meno je obsadené prosím vyberte si iné!');
$form->addText('umail', 'Emailová adresa:')
->setRequired('Email je povinný!')
->addRule(Form::EMAIL, 'Zadajte prosím, platnú emailovú adresu!')
->addRule(function($input) use($userRepository)
{
return !$userRepository->usermailexists($input->value);
}, 'Táto emailová adresa je už v systéme zaregistrovaná!');
$form->addPassword('password', 'Heslo:')
->setRequired('Heslo je povinné!')
->addRule(Form::MIN_LENGTH, 'Heslo musí obsahovať min. %d znaky', 4);
$sex = array('m' => 'Muž','f' => 'Žena',);
$form->addRadioList('ugender', 'Pohlavie:', $sex)
->setRequired() // Rules is gender checked?
->getSeparatorPrototype()->setName(NULL);
$form->addDatePicker('birthDate', 'Dátum Narodenia:')
->setAttribute('class', 'birthDate')
->addRule(Form::VALID, 'Entered birth date is not valid!');
$ucountries = $this->CountryList();
$prompt = Html::el('option')->setText('Vyberte Krajinu')->class('prompt');
$form->addSelect('ucountry', 'Krajina:', $ucountries)
->setPrompt($prompt)
->setRequired();
$form->addCheckBox('uagree', Html::el('span')
->setHtml('Súhlasím s <a href="../docs/Terms" target="_blank">Podmienkamy</a>'))
->setDefaultValue(TRUE)
->addRule(Form::EQUAL, 'Musíte súhlasiť s podmienkamy!', TRUE);
$form->addSubmit('uregme', 'Registrovať');
$form->onSuccess[] = $this->UserSuccessRegisterSubmitted;
$form->addProtection();
return $form;
}
public function UserSuccessRegisterSubmitted(Form $form)
{
$values = $form->getValues();
$this->salt->passwordHasher($values->password);
dump($values);
//$this->users->insert($values);
//$this->flashMessage('Čo sa deje?');
//$this->redirect('Index:index');
/*if ($e->getCode() === 23000) {
//pokud je chyba v duplicitě klíče, přidáme chybu do formu
$form->addError('Chyba');
} else {
//pokud jde o jinou chybu, necháme ji probublat výš
throw $e;
}
*/
}
}
Všetko funguje ok až na to že nič nehashuje :)
Čo zas ja hlavaMaková robím zle?
Prešiel som 7× Přihlašování uživatelů->Authenticator
podľa odkazu od Draffix neprišiel som na to :)
Sorry posledná žiadosť o pomoc s reg.
- David Matějka
- Moderator | 6445
kde si zjistil ze to nic nehashuje? mam ten kod brat doslovne, ze jsi to
zjistil dle dump($values);
? v tom bude samozrejme heslo
v plaintextu, ten hash je navratova hodnota te
fce passwordHasher
jo a kdyz tu funkci passwordHasher pouzivas nestaticky, tak u ni nemej to slovo static :)
Editoval matej21 (27. 3. 2013 0:26)
- SontoEremo
- Člen | 341
matej21 napsal(a):
kde si zjistil ze to nic nehashuje? mam ten kod brat doslovne, ze jsi to zjistil dle
dump($values);
? v tom bude samozrejme heslo v plaintextu, ten hash je navratova hodnota te fcepasswordHasher
jo a kdyz tu funkci passwordHasher pozivas nestaticky, tak u ni nemej to slovo static :)
Pri zápise do DB stále to bolo len 123456
Nie dump to som iba len skúšal …
- David Matějka
- Moderator | 6445
no ale ty tam nic nedelas s tim vysledkem s passwordHasher.. treba tohle:
$values->password = $this->salt->passwordHasher($values->password);
- SontoEremo
- Člen | 341
matej21 napsal(a):
no ale ty tam nic nedelas s tim vysledkem s passwordHasher.. treba tohle:
$values->password = $this->salt->passwordHasher($values->password);
Ježiši ja HlavaDubová…
Opravma! ak som to správne pochopil…
políčko->password sa rovná toto zahashuj pomocou passwordHasera(kde políčko->je password);
- spaze
- Generous Backer | 28
SontoEremo napsal(a):
$salt = '$2a$07$' . Strings::random(22);
Salt začínající na $2a$ nepoužívej. Použij $2y$,
pokud máš PHP novější, než 5.3.7 (a to asi máš). A pokud chceš
jednodušší hashování a ověřování, tak použij balíček https://github.com/…word_compat/ –
dodá funkce password_hash()
a password_verify()
z PHP 5.5 i do starších verzí.