Po přihlášení stále bez identity :/
- mimacala
- Člen | 113
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 | 322
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
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 | 322
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
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 | 822
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 | 822
Servicu nemusíš pojmenovávat, pokud se na ni nepotřebuješ někde jinde odkázat (v neonu přes @).
- Marek Bartoš
- Nette Blogger | 1280
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 | 322
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
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é 4xx 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 | 822
@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)