Registrace uživatele a ověření pomocí mailu

jAkErCZ
Člen | 322
+
0
-

Zdravím,
Rozhodl jsem se že bych si rád udělal registraci do systému ve které by bylo zakomponováno ověření uživatele pomocí mailu a také že pokud není ověření nepříhlásí ho to.

Zatím mám:

		public function create(callable $onSuccess)
	{
		$form = $this->formFactory->create();
		$form->addText('username', 'Jméno')->setRequired();
		$form->addEmail('email','')->setRequired();
		$form->addPassword('password', 'Heslo');
		$form->addPassword('password_repeat', 'Heslo znovu')->setOmitted()->setRequired(false)
			->addRule(Form::EQUAL, 'Hesla nesouhlasí.', $form['password']);
		$form->addCheckbox('conditions','')->setRequired();
		$form->addSubmit('register', 'Registrovat');

		$form->onSuccess[] = function (Form $form, ArrayHash $values) use ($onSuccess) {
$latte = new \Latte\Engine;
		    try {
    $now = new DateTime();
    $validity = new DateTime('+1 day');
    $values->passwordHash(Passwords::hash($now . $values->email));
    $values->passwordHashValidity($validity);
    // Zkusíme zaregistrovat nového uživatele.
    $this->userManager->register($values->username, $values->password);

    $message = new Message;

    $params = [
        'username' => $values->username,
        'token' => $values->passwordHash,
    ];
    $message->setFrom('noreply@mail.cz')
        ->addTo($values->email)
        ->setSubject('Aktivace účtu')
        ->setHtmlBody($latte->renderToString(__DIR__ . '/templates/Sign/rememberMail.latte', $params));

    $mailer = $this->setMailer();

				$onSuccess($form, $values); // Zavoláme specifickou funkci.
    $form->getParent()->flashMessage('Zkontrolujte si prosím svou mailovou schránku', 'success');
			} catch (DuplicateEmailException $e) {
    // Přidáme chybovou zprávu alespoň do formuláře.
    $form->getParent()->flashMessage($e->getMessage(), 'error');
			}
		};

		return $form;
	}

A jak teď dál postupovat? A třeba jak udělat že pokud není účet aktivovaný že se nepřihlásí.

Nebo nějaké efektivnější řešení?

Díky

Editoval jAkErCZ (26. 11. 2018 14:42)

Phalanx
Člen | 310
+
0
-
  1. Vytvoř si jen v databázi sloupec u uživatele active, který bude mít hodnotu 0 nebo 1, výchozí 0. Tuto hodnotu kontroluj tam, kde se uživatel přihlašuje.
  2. Do mailu bych taky přidal nějaký unikátní hash na ověření. Takže pak klikne například na /over-uzivatele/hash=abcdefgh

Takže do databáze ti přibudou sloupce
active
hash

Tyto sloupce si nastavíš při registraci.

Pak přidáš parametr do mailu hash a povedeš odkaz s tímto parametrem na nějakou akci.

<?php
public function handleActiveUser($hash)
{
	// find user by unique hash
	// set active to 1
	// login user
	// redirect
}
?>

Tam kde se u6ivatel přihlašuje se kontroluje email a heslo. K tomu ještě doplníš kontrolu active. Pokud je active 0, pak můžeš vypsat, že si musí nejdřív účet aktivovat.

Editoval Phalanx (26. 11. 2018 14:58)

David Matějka
Moderator | 6445
+
0
-

ve zkratce: v databazi u uzivatele budes mit priznak, zda byl overen email. do databaze si ulozis nejaky token, ktery soucasne posles uzivateli v aktivanich odkazu. po kliknuti na odkaz, ktery si mu poslal, se nastavi na true (v pripade, ze sedi ten token).
v authenticatoru zkontrolujes, zda je ten priznak na true, a pripadne vyhodis vyjimku (podobnou te, kterou vyhazujes pri nespravnem heslu)

a par poznamek ke kodu:

  1. ->setRequired(false) ti zapricini, ze uzivatel nemusi vyplnovat password_repeat
  2. co si myslis, ze bude delat
$values->passwordHash(Passwords::hash($now . $values->email));
$values->passwordHashValidity($validity);

(respektive proc to volas jako funkci – to nemuze fungovat)

3. instanci latte engine vytvarej pres sluzbu ILatteFactory
4. v $onSuccess provadis (predpokladam) redirect. pokud tedy volas flashMessage za radkem, kde onSuccess volas, tak se flash message nezavola
5. co dela metoda setMailer() a proc neco vraci? nemela by se tedy jmenovat getMailer?
6. a ten mail ani neodesilas

jAkErCZ
Člen | 322
+
0
-

David Matějka napsal(a):

ve zkratce: v databazi u uzivatele budes mit priznak, zda byl overen email. do databaze si ulozis nejaky token, ktery soucasne posles uzivateli v aktivanich odkazu. po kliknuti na odkaz, ktery si mu poslal, se nastavi na true (v pripade, ze sedi ten token).
v authenticatoru zkontrolujes, zda je ten priznak na true, a pripadne vyhodis vyjimku (podobnou te, kterou vyhazujes pri nespravnem heslu)

a par poznamek ke kodu:

  1. ->setRequired(false) ti zapricini, ze uzivatel nemusi vyplnovat password_repeat
  2. co si myslis, ze bude delat
$values->passwordHash(Passwords::hash($now . $values->email));
$values->passwordHashValidity($validity);

(respektive proc to volas jako funkci – to nemuze fungovat)

3. instanci latte engine vytvarej pres sluzbu ILatteFactory
4. v $onSuccess provadis (predpokladam) redirect. pokud tedy volas flashMessage za radkem, kde onSuccess volas, tak se flash message nezavola
5. co dela metoda setMailer() a proc neco vraci? nemela by se tedy jmenovat getMailer?
6. a ten mail ani neodesilas

  1. O tom setRequired(false) vím.
  2. No myslel jsem že mi to vezme aktuální datum + mail a vytvoří z toho has a validity nastaví 1 den… a pokud člověk klikne na odkaz až třeba den druhý tak se provede kontrolu hashu a jestli sedí tak aktivuje a pokud ne bude muset si člověk nechat zaslat nový… Vycházel jsem jednoho návodu na ztracené heslo → http://rudolfsvatek.cz/…menuta-hesla
  3. Ok to jsem nevěděl mrknu na to :)
  4. Ano tam provádím redirect.. to též vím :)
  5. Tam mám mít funkci new SendmailMailer;
  6. ano tu metodu jsem si tam dodal.. $mailer->send($mail);

Nějaký návrh tedy na ten hash, kontrola a případný rehash?

Editoval jAkErCZ (26. 11. 2018 15:11)

David Matějka
Moderator | 6445
+
0
-

ad 2: ale passwordHash ani passwordHashValidity nejsou funkce

ten clanek je divny a plete tam ruzne pojmy a postupy. vubec bych dle nej nepostupoval

  1. vygeneruj si pomoci Random::generate nahodny token (treba 20 znaku). ten si pri registraci ulozis do databaze k uzivateli – pojmenovane jako treba verificationToken
  2. v mailu posles uzivateli link na nejaky VerificationPresenter s tim tokenem jako parametrem (plus id uzivatele)
  3. po kliknuti na odkaz se ve VerificationPresenteru nastavi v db ten uzivatel jako verified
  4. v authenticatoru overis, zda je uzivatel verified
jAkErCZ
Člen | 322
+
0
-

David Matějka napsal(a):

ad 2: ale passwordHash ani passwordHashValidity nejsou funkce

ten clanek je divny a plete tam ruzne pojmy a postupy. vubec bych dle nej nepostupoval

  1. vygeneruj si pomoci Random::generate nahodny token (treba 20 znaku). ten si pri registraci ulozis do databaze k uzivateli – pojmenovane jako treba verificationToken
  2. v mailu posles uzivateli link na nejaky VerificationPresenter s tim tokenem jako parametrem (plus id uzivatele)
  3. po kliknuti na odkaz se ve VerificationPresenteru nastavi v db ten uzivatel jako verified
  4. v authenticatoru overis, zda je uzivatel verified

Ok super, a co když bych rád udělal že ten aktivační mail budu aktivní třeba jen hodinu?

Pavel Kravčík
Člen | 1196
+
+2
-

Tak si tam dáš datum expirace třeba jen na hodinu?

jAkErCZ
Člen | 322
+
0
-

Pavel Kravčík napsal(a):

Tak si tam dáš datum expirace třeba jen na hodinu?

Ale to vím spíše přemýšlím na jaké bázi mám udělat to omezení? Jestli to už mohu nějak udělat do odkazu nebo jak to kontrolovat…

MajklNajt
Člen | 502
+
0
-

jAkErCZ napsal(a):

Pavel Kravčík napsal(a):

Tak si tam dáš datum expirace třeba jen na hodinu?

Ale to vím spíše přemýšlím na jaké bázi mám udělat to omezení? Jestli to už mohu nějak udělat do odkazu nebo jak to kontrolovat…

napr. budeš mať v DB vedľa verificationToken aj verificationTokenValidUntil, kde si pri registrácií (pri ukladaní tokenu) uložíš aktuálny dátum + 1 hod

jAkErCZ
Člen | 322
+
0
-

MajklNajt napsal(a):

jAkErCZ napsal(a):

Pavel Kravčík napsal(a):

Tak si tam dáš datum expirace třeba jen na hodinu?

Ale to vím spíše přemýšlím na jaké bázi mám udělat to omezení? Jestli to už mohu nějak udělat do odkazu nebo jak to kontrolovat…

napr. budeš mať v DB vedľa verificationToken aj verificationTokenValidUntil, kde si pri registrácií (pri ukladaní tokenu) uložíš aktuálny dátum + 1 hod

Dobrá to chápu a jakou formou budu ověřovat?

MajklNajt
Člen | 502
+
+2
-

žeby?

if($row->verificationTokenValidUntil >= Nette\Utils\DateTime::from("now")) {
	...
}