Po přihlášení stále bez identity :/

mimacala
Člen | 113
+
0
-

Zdravím,
po přihlášení mi tracy stále ukazuje, že nemám žádnou identitu.

Cookies v prohlížeči jsou povolené i promazané, expirace nastavena v nette na 1 den.
Prosím berte můj kód trochu s rezervou (napůl česky|anglicky) → bez továrničky atd.. v nette se opravdu teprve učím.

<?php

namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;

use App\model\Kontrola;
use Nette\Security\SimpleIdentity;

class PrihlaseniPresenter extends Nette\Application\UI\Presenter
{
    private Nette\Database\Explorer $database;
    private Kontrola $kontrola;
    public function __construct(Nette\Database\Explorer $database, Kontrola $kontrola)
    {

        $this->database = $database;
        $this->kontrola = $kontrola;

    }
    protected function createComponentPrihlasit(): Form
    {
        $form = new Form;
        $form->addText('email', 'Email:');
        $form->addPassword('heslo', 'Heslo:');
        $form->addSubmit('send', 'Přihlásit');
        $form->onSuccess[] = [$this, 'formSucceeded'];
        return $form;
    }

    public function formSucceeded(Form $form, $data): void
    {


        $this->kontrola->authenticate($data->email, $data->heslo);
        $this->redirect("Homepage:default");

    }
}
<?php

namespace App\model;

use Nette;
use Nette\Security\Authenticator;
use Nette\Security\SimpleIdentity;

class Kontrola implements Authenticator
{
    use Nette\SmartObject;
    private Nette\Database\Explorer $database;
    private Nette\Security\Passwords $passwords;

    public function __construct(
        Nette\Database\Explorer $database,
        Nette\Security\Passwords $passwords
    ) {
        $this->database = $database;
        $this->passwords = $passwords;
    }

    public function authenticate(string $email, string $password): SimpleIdentity
    {
        $row = $this->database->table('uzivatele')
            ->where('email', $email)
            ->fetch();

        if (!$row) {
            throw new Nette\Security\AuthenticationException('User not found.');
        }

        if (!$this->passwords->verify($password, $row->heslo)) {
            throw new Nette\Security\AuthenticationException('Invalid password.');
        }

        return new Nette\Security\SimpleIdentity($row->id, $row->role);
    }
}

Zkusil jsem i natvrdo odeslat data do formSucceeded ale opět kód proběhne bez chybové hlášky a moje identita stále nikde :D .

 public function formSucceeded(Form $form, $data): void
    {

		new Nette\Security\SimpleIdentity("12", $data->email);
       /*$this->kontrola->authenticate($data->email, $data->heslo);
        $this->redirect("Homepage:default");*/

    }

Moc děkuji za veškeré rady.

jAkErCZ
Člen | 321
+
+1
-

Jelikož uživatele nikde nepřihlašuješ.

Viz

try {
	$user->login($username, $password);
} catch (Nette\Security\AuthenticationException $e) {
	$this->flashMessage('Uživatelské jméno nebo heslo je nesprávné');
}

Přečti si https://doc.nette.org/…thentication

mimacala
Člen | 113
+
0
-

Mám v tom teď trošku zmatek.
Tedy pro upřesnění

Zkontroluje zda email a heslo sedí s DB (toto chápu jako validní příhlášení)

$this->kontrola->authenticate($data->email, $data->heslo);

a pokud ano tak vytvoří instanci uživatele s argumenty ID a role a ty uloží to session ?

return new Nette\Security\SimpleIdentity($row->id, $row->role);

Děkuji za upřesnění.

jAkErCZ
Člen | 321
+
+1
-

Takto

public function formSucceeded(Form $form, $data): void
{
	try {
           $this->getUser()->login($data->email, $data->heslo); //Pokusíme se přihlásit uživatele
           $this->redirect('this'); // kam uživatele přesměrujeme
        } catch (AuthenticationException $e) {
            $form->getParent()->flashMessage($e->getMessage(), 'r');
        }
}

Editoval jAkErCZ (5. 1. 2022 22:32)

mimacala
Člen | 113
+
0
-

Skvělé funguje,
mohu se zeptat jak nette pozná že má použít můj model Kontrola.php místo klasické

security:
	users:

Děkuji

Kamil Valenta
Člen | 752
+
+1
-

V neonu:

services:
	authenticator: App\Model\Kontrola
mimacala
Člen | 113
+
0
-

Mám to tam přidané takto, nette sám rozpozná authenticator ?

services:
	- App\Router\RouterFactory::createRouter
	- App\model\Kontrola
	- App\model\BaseModel

nebo je potřeba ještě to upravit na tuto formulaci i přes to, že to funguje.

services:
	authenticator: App\Model\Kontrola
	- App\Router\RouterFactory::createRouter
	- App\model\BaseModel

Děkuji

Kamil Valenta
Člen | 752
+
+1
-

jAkErCZ napsal(a):

Takto

public function formSucceeded(Form $form, $data): void
{
	catch (AuthenticationException $e) {
      $form->getParent()->flashMessage($e->getMessage(), 'r');
  }
}

Je to trochu mimo téma, ale není moc dobré dávat znění exceptiony do flashmsg. Koncový uživatel tomu stejně nebude rozumět a může to nechtěně vynést nějakou citlivou informaci. Takové věci patří do logu.

Kamil Valenta
Člen | 752
+
+1
-

Servicu nemusíš pojmenovávat, pokud se na ni nepotřebuješ někde jinde odkázat (v neonu přes @).

Marek Bartoš
Nette Blogger | 1146
+
+2
-

Nejpřímější cesta je

$identity = $this->kontrola->authenticate($data->email, $data->heslo);
$this->getUser()->login($identity);

Předpokládá, že do Usera předáváš Identitu již ověřeného uživatele. Authenticator interface můžeš de facto smazat, zbytečně tě omezuje na jméno a heslo a nedává smysl ho nastavovat do Usera.

jAkErCZ
Člen | 321
+
0
-

Kamil Valenta napsal(a):

jAkErCZ napsal(a):

Takto

public function formSucceeded(Form $form, $data): void
{
	catch (AuthenticationException $e) {
      $form->getParent()->flashMessage($e->getMessage(), 'r');
  }
}

Je to trochu mimo téma, ale není moc dobré dávat znění exceptiony do flashmsg. Koncový uživatel tomu stejně nebude rozumět a může to nechtěně vynést nějakou citlivou informaci. Takové věci patří do logu.

Jde taky o to co si do exception posíláš :

Polki
Člen | 553
+
+1
-

jAkErCZ napsal(a):

Kamil Valenta napsal(a):

jAkErCZ napsal(a):

Takto

public function formSucceeded(Form $form, $data): void
{
	catch (AuthenticationException $e) {
      $form->getParent()->flashMessage($e->getMessage(), 'r');
  }
}

Je to trochu mimo téma, ale není moc dobré dávat znění exceptiony do flashmsg. Koncový uživatel tomu stejně nebude rozumět a může to nechtěně vynést nějakou citlivou informaci. Takové věci patří do logu.

Jde taky o to co si do exception posíláš :

Přesně viděl jsem už weby, které systémové exc odchytávali a vyhazovali si svoje, jež jsi rozlišil na základě názvu a potom pokud měly kód nějaký specifický, třeba PHP_INT_MAX, tak věděli, že hláška je určená pro uživatele a jinak je to systémová chyba, kterou nestihli odchytit a vypsali prostě ‚neznámá chyba‘.

Jiné zase toto řešili tím, že nevěděli, který kód si zvolit, tak povolené hlášky na výpis (pro uživatele) prefixovali nějakým řetězcem, třeba ‚ALLOWED – ' což jim dávalo znamení, že se hláška může vypsat, jinak zase 'neznámá chyba‘.

Další to řeší tak, že mají speciální třídu dědící od Exception, která to rozlišuje. Například se jmenuje ‚AllowedMessageException‘ a když je tato vyhozena je jasné, že je povoleno vypsat error uživateli.

To se hodí například v různých API, kde různé 4×x hlášky vyhazuješ ty a vyhazuješ je pomocí Nette\Application\BadRequestException s vlastním textem.

U příkladu tazatele si to dokážu takto představit, jelikož AuthenticationException je třída, která se nikde nepoužívá a je určená jen pro autentizaci, takže si člověk může být na 100% jistý, že to, co odchytí v tom catchi bue hláška, kterou si tam sám dal a pokud tam dal hlášky typu ‚Uživatel neexistuje‘ nebo ‚Nesprávné heslo‘ stejně jak je to v dokumentaci ve třídě MyAuthenticator, tak v tomto případě je to ok.

Editoval Polki (6. 1. 2022 11:37)

Kamil Valenta
Člen | 752
+
+2
-

@jAkErCZ ano, já jsem to vztahoval třeba k exceptionám z db apod. Pokud si vykopneš vlastní exceptionu, může (nebo stále nemusí) to být ok.

Polki napsal(a):

U příkladu tazatele si to dokážu takto představit, jelikož AuthenticationException je třída, která se nikde nepoužívá a je určená jen pro autentizaci, takže si člověk může být na 100% jistý, že to, co odchytí v tom catchi bue hláška, kterou si tam sám dal a pokud tam dal hlášky typu ‚Uživatel neexistuje‘ nebo ‚Nesprávné heslo‘ stejně jak je to v dokumentaci ve třídě MyAuthenticator, tak v tomto případě je to ok.

Zrovna u příkladu tazatele to osobně za vhodné nepovažuji. Sdělit uživateli, že uživatel neexistuje, nebo že zadal chybné heslo, je vynesení zneužitelného detailu. Ale samozřejmě je důležité jak vypadá zbytek.
Měl jsem ale původně na mysli situace, kdy na uživatele vypadne anglická hláška vyzrazující adresářovou strukturu nebo strukturu db. Byla to jen poznámka bokem, tak bych to nerad v tomto vlákně rozvíjel.

Editoval Kamil Valenta (6. 1. 2022 13:10)

mimacala
Člen | 113
+
+1
-

Moc děkuji všem, nyní šlape jak má :D