Login nefunguje (Authenticator / UserManager)

iDome89
Člen | 27
+
0
-

Ahoj,

opět se s nečím peru v Nette :D Mam UserManager(Authenticator) ulozený ve službách, mám Login Form s vlastním presenterem, ale ne a ne se přihlásit s přesměrováním. Nemáte radu jak napsat methodu „onFormSuccess“ která toto udělá?
Kvůli přehlednosti jsem to hodil na Github abych tu nepostoval X řádků kódu.

https://github.com/…9/Calculator

Kamil Valenta
Člen | 762
+
0
-

Ten authenticator tě buď vyhodí výjimku, nebo vrátí identitu. Takže v onFormSuccess si to obal try-catch a zareaguj, pokud k výjimce došlo.

David Matějka
Moderator | 6445
+
0
-

plus on authenticator pouze vrací identitu, ale nepřihlásí tě. to musíš udělat skrz třídu Nette\Security\User, viz https://github.com/…mFactory.php – do login můžeš buď poslat login + password a NS\User to pošle na Authenticator (tak je to v sandboxu) nebo tam můžeš jako jediný parametr poslat Identitu, kterou ti vrátil authenticator

iDome89
Člen | 27
+
0
-

David Matějka napsal(a):

plus on authenticator pouze vrací identitu, ale nepřihlásí tě. to musíš udělat skrz třídu Nette\Security\User, viz https://github.com/…mFactory.php – do login můžeš buď poslat login + password a NS\User to pošle na Authenticator (tak je to v sandboxu) nebo tam můžeš jako jediný parametr poslat Identitu, kterou ti vrátil authenticator

Díky moc, já jsem to právě nechápal úplně jak to funguje, teď už v tom mám jasno.

iDome89
Člen | 27
+
0
-

David Matějka napsal(a):

plus on authenticator pouze vrací identitu, ale nepřihlásí tě. to musíš udělat skrz třídu Nette\Security\User, viz https://github.com/…mFactory.php – do login můžeš buď poslat login + password a NS\User to pošle na Authenticator (tak je to v sandboxu) nebo tam můžeš jako jediný parametr poslat Identitu, kterou ti vrátil authenticator

Ještě mám jeden dotaz, protože jsem očividně dutej jak bambus, chci vyřešit 2 věci ve kterých se nejsem schopnej orientovat. V přihlášení mi nefunguje catch kde jakmile dám špatný heslo nebo jmeno tak mě hodí tracy error a nedostanu např. jen hlášku „špatné jmeno“ atd. Druhá věc je, v BasePresenteru bych chtěl udělat tak aby, když uživatel je isLoggedIn() tak mě přesměruje automaticky na Homepage abych předešel tomu že uživatel napíše do prohlížeče URL adresu na Login form a bude se moci znovu přihlásit. Nevím jestli jsem to napsal srozumitelně.

Kamil Valenta
Člen | 762
+
0
-

Ukaž ten catch, na gitu to asi nemáš.

Jinak, v BasePresenteru bys asi přihlášeného uživatele nikam přesměrovávat neměl, pokud z BasePresenter budou dědit všechny ostatní presentery. Vyřeš to pouze v LoginPresenter u příslušné actiony.

iDome89
Člen | 27
+
0
-

kamil_v napsal(a):

Ukaž ten catch, na gitu to asi nemáš.

Jinak, v BasePresenteru bys asi přihlášeného uživatele nikam přesměrovávat neměl, pokud z BasePresenter budou dědit všechny ostatní presentery. Vyřeš to pouze v LoginPresenter u příslušné actiony.

Já to právě bral tak, že pokud uživatel bude ručně chtít na jinou adresu. Např homepage když nebude loggedIn, tak ho to přesměruje zpátky na Login Form. Mám se co učit pořád samozřejmě, ale hlavně to potřebuju chápat :D

<?php

declare(strict_types=1);

namespace App\Presenters;

use App\Forms\FormFactory;
use Nette\Application\UI\Form;
use Nette\Database\Context;
use Nette\Utils\ArrayHash;

class LoginPresenter extends BasePresenter
{

    /**
     * @var FormFactory
     * @inject
     */
    public $formFactory;

	/**
	 * @var Context
	 * @inject
	 */
	public $database;


	protected function createComponentLoginForm(): Form
	{
        $form = $this->formFactory->create();

		$form->addText('username', 'Uživatelské jméno:')
			->setRequired('Prosím vyplňte své uživatelské jméno.');

		$form->addPassword('password', 'Heslo:')
			->setRequired('Prosím vyplňte své heslo.');

		$form->addSubmit('send', 'Login');

		$form->onSuccess[] = function (Form $form, ArrayHash $values): void {
            $this->user->getAuthenticator()
                ->authenticate([$values->username, $values->password]);

            try {
                $this->user->setExpiration( '14 days');
                $this->user->login($values->username, $values->password);
                if($this->user->isLoggedIn()) {
                    $this->redirect('Homepage:default');
                }
            } catch (\Exception $e) {
                $this->flashMessage('Uživatelské jméno nebo heslo je nesprávné', 'warning');;
                return;
            }
		};

		return $form;
	}

}
?>
Kamil Valenta
Člen | 762
+
0
-

To jsou ale dvě různé věci, v předchozím postu píšeš, že chceš zamezit tomu, že ručně zadá do URL /sign/in a bude se moct znovu přihlásit. Teď píšeš, že chceš přesměrovat nepřihlášeného.

Takže postupně:

  1. Pro přesměrování nepřihlášeného: v BasePresenteru si někde ověř, že je uživatel přihlášen.
if (!$this->getUser()->isLoggedIn())
{
    $this->redirect('Sign:in');
}

Možnosti jsou třeba ve startup() nebo checkRequirements($element).
Pozor, z tohoto BasePresenteru nesmí dědit SignPresenter. Jinak bys totiž vyžadoval přihlášení i pro přihlášení :)

  1. Pro přesměrování již přihlášeného uživatele pryč z přihlašovacího formu si dej do SignPresenter actionIn():
if ($this->user->isLoggedIn())
{
    $this->redirect('Homepage:');
}
  1. Catch při přihlášení. Tohle máš v docela slušném marastu.

Ten Tvůj authenticator si zaregistruj jako servicu v neonu:

services:
	authenticator: App\Model\Authenticator

V onSuccess už ho pak vůbec volat nemusíš (navíc ho máš mimo try, takže se tě výjimka nezachytí).
Zůstane tě jen volání user->login(), ta si po authenticatoru sáhne.

Jo a ještě: nedělej po úspěšném přihlášení redirect v továrničce formuláře. Jednak by se o redirect měl postarat Presenter, který továrničku zavolal, druhak redirecty vyvolávají výjimku, takže by tě to asi vždy padlo do catch.

Editoval kamil_v (11. 9. 2019 22:07)