Nette – authenticator …

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Takeshi
Člen | 596
+
0
-

Caute … viete ako pouzit authenticator, aby mi tahalo udaje z databazy
… zatial pouzivam toto … na zaciatok

<?php
$authenticator = new Nette\Security\SimpleAuthenticator(array(
            'john' => 'pass1',
            'kathy' => '12345', // Kathy, this is a very weak password!
            'takeshi' => 'kitano'
        ));
        $user->setAuthenticator($authenticator);
?>

je tam spomenuty (na nette strankach) aj MyAuthenticator, ale neviem ako ho mam pouzit

Diki

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Autentikátorem může být libovolný objekt implementující rozhraní Nette\Security\IAuthenticator. Musí implementovat 1 metodu authenticate(), která buď vrací Identity (při úspěšném přihlášení) nebo NULL. Nejsnáze se nastavuje v configu (doufám že nekecám a toto funguje):

services:
	authenticator:
		class: MyAuthenticator

Možná by Takeshi bylo fajn nebojovat s minimálním limitem subjektu vláken a snažit se vyplodit popisnější název problému. Mohlo by to do budoucna pomoci i ostatním.

Takeshi
Člen | 596
+
0
-

vojtech.dobes napsal(a):

Co sa tyka konfiguracie, mam to nastavene takto, a nefunguje

	services:
		database: @Nette\Database\Connection

		authenticator: MyAuthenticator( @database::table(users) )

takze ak mas prosim inu radu, sem s nou :-) … a co sa tyka toho mojho skrateneho textu … ja osm mal pocit ze som ho nacrtol jasne … no mozno nie (ale to som potom nemal v plane)

vvoody
Člen | 910
+
0
-

definuj „nefunguje“

Takeshi
Člen | 596
+
0
-

Mam to nastavene, ako je napisane vyssie, ale meno a heslo, ktore mam v databaze mi neakceptuje …

Takeshi
Člen | 596
+
0
-

OK tak ten moj problem upresnim: Potrebujem aby mi udaje (username, password, role [user,admin]) nacitavalo z databazy … pre istotu ukazem moj Presenter a pod nim aj configuracny subor config.neon ..

<?php

class LoginPresenter extends BasePresenter
{
    public function renderDefault()
    {
        $user = $this->getUser();

        if($user->isLoggedIn()){
            $this->redirect('Homepage:default');
        }

        $authenticator = new Nette\Security\SimpleAuthenticator(array(
            'john' => 'pass1',
            'kathy' => '12345', // Kathy, this is a very weak password!
            'takeshi' => 'kitano'
        ));
        $user->setAuthenticator($authenticator);

        if ($this['login']->isSuccess()){
            $username = $_POST['username'];
            $password = $_POST['password'];
        /*Pokusa sa prihlasit*/
            try {
                // pokusíme se přihlásit uživatele...
                $user->login($username, $password);
            $this->redirect('Homepage:default');
                // ...a v případě úspěchu presměrujeme na další stránku
                //$this->redirect('Homepage:default');
            } catch (Nette\Security\AuthenticationException $e) {
                $e->getMessage();
            }
        }
    }

    public function createComponentLogin(){
        $form = new Nette\Application\UI\Form;
        $form->setAction('');
        $form->setMethod('POST');
        $form->addText('username',null,16);
        $form->addPassword('password',null,16);
        $form->addSubmit('login','Login');

        return $form;
    }
}
?>
#
# SECURITY WARNING: it is CRITICAL that this file & directory are NOT accessible directly via a web browser!
#
# If you don't protect this directory from direct web access, anybody will be able to see your passwords.
# https://nette.org/en/security-warning
#
common:
	parameters:
		database:
			driver: mysql
			host: localhost
			dbname: database
			user: root
			password:


	php:
		date.timezone: Europe/Prague
		# session.save_path: "%tempDir%/sessions"
		# zlib.output_compression: yes


	nette:
		session:
			expiration: '+ 14 days'

		database:
			default:
				dsn: '%database.driver%:host=%database.host%;dbname=%database.dbname%'
				user: %database.user%
				password: %database.password%


	services:
		database: @Nette\Database\Connection

		authenticator: MyAuthenticator( @database::table(users) )




	factories:


production < common:

development < common:

.. a s tymto nastavenim mi to nefunguje, viete preco? (MyAuthenticator.php (ktorý je aj v Nette dokumentacií) mám uložený v priečinku models)

Editoval Takeshi (22. 4. 2012 14:23)

Takeshi
Člen | 596
+
0
-

A ked ten MyAuthenticator zaregistrujem …$user->setAuthenticator(new MyAuthenticator); ukazuje mi nasledovnu chybu

Argument 1 passed to MyAuthenticator::__construct() must be an instance of Nette\Database\Connection, none given, called in C:\Program Files (x86)\EasyPHP-5.3.8.0\www\PUSKAS\app\presenters\LoginPresenter.php on line 20 and defined
ricco24
Člen | 141
+
0
-

Skús zaregistrovať authenticator takto

$user->setAuthenticator($this->context->authenticator)

//EDIT:
Pre istotu ešte otázka triedu MyAuthenticator ktorá implementuje Nette\Security\IAuthenticator máš vytvorenú ?

Editoval ricco24 (22. 4. 2012 15:18)

Takeshi
Člen | 596
+
0
-

ricco24 napsal(a):

1. Pouzitim registracie: $user->setAuthenticator($this->context->authenticator); mi hlasi nasledovnu chybu

Argument 1 passed to MyAuthenticator::__construct() must be an instance of Nette\Database\Connection, instance of Nette\Database\Table\Selection given, called in C:\Program Files (x86)\EasyPHP-5.3.8.0\www\PUSKAS\temp\cache\_Nette.Configurator\_-285bac8f7b7d3ea72485a759a142673d.php on line 108 and defined search►

a pre ISTOTU este raz ukazem moj Presenter … (trosicka zmeneny)

<?php

class LoginPresenter extends BasePresenter
{
    public function renderDefault()
    {
        $user = $this->getUser();

        if($user->isLoggedIn()){
            $this->redirect('Homepage:default');
        }

        $user->setAuthenticator($this->context->authenticator);

        if ($this['login']->isSuccess()){
            $username = $_POST['username'];
            $password = $_POST['password'];
        /*Pokusa sa prihlasit*/
            try {
                // pokusíme se přihlásit uživatele...
                $user->login($username, $password);
            $this->redirect('Homepage:default');
                // ...a v případě úspěchu presměrujeme na další stránku
                //$this->redirect('Homepage:default');
            } catch (Nette\Security\AuthenticationException $e) {
                $e->getMessage();
            }
        }
    }

    public function createComponentLogin(){
        $form = new Nette\Application\UI\Form;
        $form->setAction('');
        $form->setMethod('POST');
        $form->addText('username',null,16);
        $form->addPassword('password',null,16);
        $form->addSubmit('login','Login');

        return $form;
    }
}
?>

2. MyAuthenticator.php mam vytvorenu:
Nazov_Projektu
|
|-app
|-models
|-MyAuthenticator.php

3. Konfiguracny dubor je nacrtnuty vyssie

ricco24
Člen | 141
+
0
-

Radšej napíš obsah triedy MyAuthenticator podla chyby to vyzerá ako by si mu v konšturktore definoval parameter Nette\Database\Connection no treba mu definovať Nette\Database\Table\Selection

davidm
Člen | 81
+
0
-

spatne registrujes authenticator v configu (predavas mu spatnou sluzbu). nevidim duvod proc nastavovat auth pres setAuthenticator … o to se ti postara autowiring

ricco24
Člen | 141
+
0
-

Pozrel som si ako je napísaný MyAuthenticator v dokumentácii.

v config.neon by si mal teda mať toto

services:
        database: @Nette\Database\Connection

        authenticator: MyAuthenticator( @database )

Je pravda že v prípade ak máš v configu len jeden Authenticator tak riadok

$user->setAuthenticator($this->context->authenticator);

môžeš úplne vypustit.

Editoval ricco24 (22. 4. 2012 18:43)

Takeshi
Člen | 596
+
0
-

ricco24 napsal(a):

Tak tu je ta trieda … a zmenil som Nette\Database\Connection na Nette\Database\Table\Selection ako si mi poradil .. no stale chyba

<?php

use Nette\Security as NS;

class MyAuthenticator extends Nette\Object implements NS\IAuthenticator
{
    public $connection;

    function __construct(Nette\Database\Table\Selection $connection)
    {
        $this->connection = $connection;
    }

    function authenticate(array $credentials)
    {
        list($username, $password) = $credentials;
        $row = $this->connection->table('users')
            ->where('username', $username)->fetch();

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

        if ($row->password !== md5($password)) {
            throw new NS\AuthenticationException('Invalid password.');
        }

        return new NS\Identity($row->id, $row->role);
    }
}
?>

A co sa tyka config.neon, tak tam som to takisto zmenil tak ako mi to poradil ricco24

.. stale ma problem v triede MyAuthenticator vo funkcii __construct()

Takeshi
Člen | 596
+
0
-

ricco24 napsal(a):

Pokial zmenim iba tu konfiguraciu teda

services:
        database: @Nette\Database\Connection

        authenticator: MyAuthenticator( @database )

a do presentera som vlozil tak ako si mi poradil …

<?php
$user->setAuthenticator($this->context->authenticator);
?>

… tak je vsetko ok

Editoval Takeshi (22. 4. 2012 20:34)

davidm
Člen | 81
+
0
-

… zmen to zpatky na Connection a ten cfg nech jak je

Takeshi
Člen | 596
+
0
-

davidm napsal(a):

… zmen to zpatky na Connection a ten cfg nech jak je

Tak v MyAutenticate som ponechal …

Nette\Database\Connection

a configuraciu som teda nechal na ..

	services:
		database: @Nette\Database\Connection

		authenticator: MyAuthenticator( @database )

chybu mi nehadze, ale udaje mi z databazi nacitavat nechce

a aby som bol co najpresnejsi v databaze mam tabulku:

users (id,username,password,role)

a s registraciou/bez .. je to rovnake

$user->setAuthenticator($this->context->authenticator);
JuniorJR
Člen | 181
+
0
-

Jenom takový „detail“, ta tvá logika by měla být spíše v action fázi, nikoliv až v render.

Takeshi
Člen | 596
+
0
-

JuniorJR napsal(a):

Jenom takový „detail“, ta tvá logika by měla být spíše v action fázi, nikoliv až v render.

Jasne presunul som :-)

davidm
Člen | 81
+
0
-

Jenom takový „detail“, ta tvá logika by měla být spíše v action fázi, nikoliv až v render.

ona by spis mela bejt v nakym callbacku navazanym na onSuccess

Takeshi
Člen | 596
+
0
-

No tak ci tak mi to zatial nefunguje :-)

JuniorJR
Člen | 181
+
0
-

davidm napsal(a):
ona by spis mela bejt v nakym callbacku navazanym na onSuccess

Souhlasím a nechápu, proč dotyčný píše:

$username = $_POST['username'];
$password = $_POST['password'];

Doporučuju ti vypsat hodnoty, které se pošlou z formuláře a ověřit, zda se opravdu shodují s hodnotami v db.

Editoval JuniorJR (22. 4. 2012 21:50)

Takeshi
Člen | 596
+
0
-

JuniorJR napsal(a):

Souhlasím a nechápu, proč dotyčný píše:

$username = $_POST['username'];
$password = $_POST['password'];

No tak vyssie je cely LoginPresenter.php, takze tie hodnoty sa najprv nacitaju do premenych a potom sa s nimi pokusam prihlasit, neviem co je na tom take nepochopitelne :-)

A pokial som pouzival (uz spomenute)

<?php
$authenticator = new Nette\Security\SimpleAuthenticator(array(
            'john' => 'pass1',
            'kathy' => '12345', // Kathy, this is a very weak password!
            'takeshi' => 'kitano'
        ));
        $user->setAuthenticator($authenticator);
?>

tak nebol ziaden problem … A ako by si mi ty doporucil tie hodnoty porovnat, ked ich neviem dostat z databazy?? … teda pokial nemyslis klasicke pouzitie Nette\database a pomocou $database->table(‚users‘) si tie vypisy porovnat … Ja by som to skor chcel iresit pomocou MyAuthenticator

Editoval Takeshi (22. 4. 2012 21:59)

ricco24
Člen | 141
+
0
-

Zdá sa mi že v tom je už príliž velký zmätok. Toto riešenie by ti malo fungovať. Inak radím ti pozrieť si aj SignPresenter zo sandboxu. Je to skoro to isté.

class LoginPresenter extends BasePresenter
{
    public function renderDefault()
    {
        $user = $this->getUser();

        if($user->isLoggedIn()){
            $this->redirect('Homepage:default');
        }
    }

   public function createComponentLoginForm(){

        $form = new Nette\Application\UI\Form;
        $form->addText('username',null,16);
        $form->addPassword('password',null,16);
        $form->addSubmit('login','Login');

	$form->onSuccess[] = callback($this, 'loginFormSubmitted')

        return $form;
   }


   public function loginFormSubmitted($form) {
	$values = $form->getValues();

        try {
                $user->login($values->username, $values->password);
                $this->redirect('Homepage:default');
            } catch (Nette\Security\AuthenticationException $e) {
                $e->getMessage();
            }
   }
}

Authenticator použijeme pre jednoduchosť ten ktorý je uvedený v dokumentácii a ktorý už máš implementovaný

use Nette\Security as NS;

class MyAuthenticator extends Nette\Object implements NS\IAuthenticator
{
    public $connection;

    function __construct(Nette\Database\Connection $connection)
    {
        $this->connection = $connection;
    }

    function authenticate(array $credentials)
    {
        list($username, $password) = $credentials;
        $row = $this->connection->table('users')
            ->where('username', $username)->fetch();

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

        if ($row->password !== md5($password)) {
            throw new NS\AuthenticationException('Invalid password.');
        }

        return new NS\Identity($row->id, $row->role);
    }
}

a v config.neon

services:
        database: @Nette\Database\Connection

        authenticator: MyAuthenticator( @database )

Dúfam že som na nič nezabudol.

Editoval ricco24 (22. 4. 2012 22:19)

ricco24
Člen | 141
+
0
-

Takeshi napsal(a):

chybu mi nehadze, ale udaje mi z databazi nacitavat nechce

Čo znamená že ti nechce načítať dáta z db ? Ak ti to nehádže chybu pri pripájaní tak si k databáze pripojený takže dáta z databázy by menal byť problém vytiahnuť …

22
Člen | 1478
+
0
-

@ricco24: toto je co if ($form->isSuccess())? nejsi náhodou v callbacku onSuccess[], tedy v callbacku, který se vykoná je v případě úspěšného odeslání?

@takeshi: v distribuci máš tvůj problém vyřešený, jmenuje se to sandbox, tam si prohlídni, ja se to správně řeší.

SimpleAuthenticator v neonu:

nette:
	security:
		users:
			admin: admin123

Editoval 22 (22. 4. 2012 22:17)

ricco24
Člen | 141
+
0
-

22 napsal(a):

@ricco24: toto je co if ($form->isSuccess())? nejsi náhodou v callbacku onSuccess[], tedy v callbacku, který se vykoná je v případě úspěšného odeslání?

Pravda. Opravil som to.

Takeshi
Člen | 596
+
0
-

No tak ja som v koncoch … chybu mi neukazuje, prihlasit sa mi aj tak neda (zmenil som config, loginPresenter, MyAuthenticator) … tak ako to urobil ricco24 a nic.

Co sa tyka SimpleAuthenticator … pomocou neho mi to islo, len som pri tom nepouyival databazu

Ak by pomohlo poslal by som aj cely moj mini-prijekt … na ktorom si skusam iba nove veci

Takeshi
Člen | 596
+
0
-

..... nieco sa mi risuje

22
Člen | 1478
+
0
-

Můžu se zeptat, proč nepoužiješ ten sandbox? Tam je přihlašování už udělané a 100% fungující…

Takeshi
Člen | 596
+
0
-

Tak po malom bádaní som zistil, že ono to pracuje s databazou dobre, teda mi najde aj danych uzivatelov, ale HESLÁ, čo sú k nim pridelené jednoducho neakceptuje …

napr.: používateľ = takeshi a heslo, nemu pridelene = kitano
teda registruje uzivatela takeshi ale neberie mi jeho heslo

Takeshi
Člen | 596
+
0
-

22 napsal(a):

Můžu se zeptat, proč nepoužiješ ten sandbox? Tam je přihlašování už udělané a 100% fungující…

Kde prosim ta najdem ten SANDBOX? som ho hladal, ale nenasiel.

Diki moc :-) … P.S skus si precitat moju predoslu spravu, ci tam nenajdes uz iba drobnu chybu

Ot@s
Backer | 476
+
0
-

Takeshi napsal(a):

Tak po malom bádaní som zistil, že ono to pracuje s databazou dobre, teda mi najde aj danych uzivatelov, ale HESLÁ, čo sú k nim pridelené jednoducho neakceptuje …

napr.: používateľ = takeshi a heslo, nemu pridelene = kitano
teda registruje uzivatela takeshi ale neberie mi jeho heslo

A není problém v tom, že máš heslo v DB jako plaintext a porovnávání se provádí oproti md5? Dumpni si výpis záznamu z DB a hned to uvidíš.

Sandbox (včetne examples) je v každé „instalačce“ Nette. Jinak viz Nette sandbox na Githubu (rovnou download).

Editoval Ot@s (22. 4. 2012 23:02)

22
Člen | 1478
+
0
-

Myslím, že Ot@s bude mít pravdu, vydumpuj si pomocí dump(), jake heslo se posílá na ověření a jaké heslo je v DB, pokud se neshodují, tak samozřejmě to přes Authenticator nemůže projít.

P.S.: Sandbox je přímo v dustribuci Nette, jeden z adresářu, kde je předpřipavená kostra aplikace a je tam i SignPresenter s přihlašovacím formulářem včetně modelu a Authenticatoru.

Editoval 22 (22. 4. 2012 23:06)

Takeshi
Člen | 596
+
0
-

No tak s tym sandboxom si to pozriem …

→ urobil som si dump() aj vypisu z formulara aj s databazy … zhoduju sa … takze neviem preco mi uzivatela berie a jeho heslo nie …

no ak nemate nejaky napad … tak len skusit stastie s tym sandboxom (vedel som o nom, len som na neho uplne zabudol … ) … ako to ja vidim,,, je tu len jedna mala blba chyba, ktora mi zneprijemnuje zivot :-) :-D .....

Takeshi
Člen | 596
+
0
-

UZ som nasiel chybu, ⇒ uz sa mi da prihlasit (pouzil som Authenticator nie MyAuth…)

CHYBA BOLA V tomto

<?php
if ($row->password !== $this->calculateHash($password)) {...}
?>

, ktory ked som zmenil na

<?php
if ($row->password !== $password) {...}
?>

tak to islo … problem pravdepodobne ale teraz nastal, ze to nebude tak bezpecne

co na to hovorite??

Myiyk
Člen | 321
+
0
-

O dost bezpečnější je ukládat heslo jako hash.
Ale jestli to spouštíš jen sám sobě na localhostu, tak je to jedno.

Takeshi
Člen | 596
+
0
-

Myiyk napsal(a):

O dost bezpečnější je ukládat heslo jako hash.
Ale jestli to spouštíš jen sám sobě na localhostu, tak je to jedno.

Ja viem, ze to je menej bezpecne, ked zamenim toto

<?php
if ($row->password !== $this->calculateHash($password)) {...}
?>

za toto …

<?php
if ($row->password !== $password) {...}
?>

… ale ked pouzijem hash, tak mam problem z heslom, teda nezhoduje sa … len v tom druhom pripade, bez calculateHash

A aby sa nepovedalo, skusal som aj prihlasovanie z prikladu, zo sandboxu, jednoducho som si skopiroval subory signPresenter a jeho sablonu, ale bez vysledne (fungovalo to iba ak som pouzil SQLITE databazu ‚demo.db‘)

Editoval Takeshi (23. 4. 2012 22:47)

duke
Člen | 650
+
0
-

Takeshi napsal(a):
… ale ked pouzijem hash, tak mam problem z heslom, teda nezhoduje sa … len v tom druhom pripade, bez calculateHash

Aby ti to fungovalo, musíš si do db to heslo ukládat zahashované. A pokud ti jde o bezpečnost, tak bys měl také solit. :-)

Takeshi
Člen | 596
+
0
-

duke napsal(a):

Takeshi napsal(a):
… ale ked pouzijem hash, tak mam problem z heslom, teda nezhoduje sa … len v tom druhom pripade, bez calculateHash

Aby ti to fungovalo, musíš si do db to heslo ukládat zahashované. A pokud ti jde o bezpečnost, tak bys měl také solit. :-)

No vidis, to som nevedel … clovek sa uci kazdym dnom :-)