Editační systém – ověření přihlášení

Panthera
Člen | 20
+
0
-

Dobrý den, potřeboval bych poradit co se přihlašování týká. Web mám rozdělený do dvou částí – AdminModule a FrontModule. Do admin sekce se přihlašuje přidáním /admin do url. Bude předložen formulář SignIn, který spravuje AuthPresenter. Authenthicator se stará o validaci hesla. Uživatel – username, password, email je uložen v databázi. Pokaždé, když se pokusím přihlásit mi to napíše, že je špatné heslo/přihlašovací jméno. Nevíte co s tím? Za každou radu budu rád :)

Authenticator

<?php
namespace App\Model;
use Nette;
use Nette\Security as NS;

/**
 * @package App\AdminModule\Model
 */
class Authenticator extends Nette\Object implements NS\IAuthenticator{
    private $database;

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

    /**
     * @param array $credentials
     *
     * @return NS\Identity
     * @throws NS\AuthenticationException
     */
    public function authenticate(array $credentials){
        list($username, $password) = $credentials;

        $user = $this->database->query("SELECT * FROM users WHERE username = '$username'");
        $hash = $this->database->fetchField("SELECT password FROM users WHERE username = '$username'");

        if(!$user) $user = $this->database->query("SELECT * FROM users WHERE email = '$username'");
        if(!$user) throw new NS\AuthenticateException("Uživatel '$username' nebyl nalezen.", self::IDENTITY_NOT_FOUND);

        $success = false;
        if(!$success && NS\Passwords::verify($password, $hash)){
            $success = true;
        }

        if(!$success){
            throw new NS\AuthenticationException("Špatně zadané heslo!", self::INVALID_CREDENTIAL);
        }

        else {
            return new NS\Identity($user->getId(), "admin", array(
                'username' => $user->username
            ));
        }
    }
}
?>

AuthPresenter

<?php

namespace App\AdminModule\Presenters;

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


/**
 * Class AuthPresenter
 * @package App\Presenters
 */

class AuthPresenter extends Nette\Application\UI\Presenter{

    protected function createComponentSignInForm(){
        $form = new Form;
        $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', 'Přihlásit');

        $form->onSuccess[] = [$this, 'signInFormSucceeded'];
        return $form;
    }

    public function signInFormSucceeded(Form $form, Nette\Utils\ArrayHash $values){
        try {
            $this->getUser()->login($values->username,$values->password);
            $user->setExpiration('20 minutes');
            $this->redirect('Dashboard:');

        } catch (Nette\Security\AuthenticationException $e) {
            $form->addError('Nesprávné přihlašovací jméno nebo heslo.');
        }
    }
}
?>
matopeto
Člen | 395
+
+1
-

nebudem odpovedat na tvoju otazku ale vsimol som si ze robis toto:

<?php

$user = $this->database->query("SELECT * FROM users WHERE username = '$username'");
        $hash = $this->database->fetchField("SELECT password FROM users WHERE username = '$username'");

?>

takto to urcite nerob a precitaj si nieco o SQL injection, ty tam mas uplne ukazkovy priklad :)

Username by malo byt escapovane, Mozes pouzit escapovanie pomocou otaznikov ? https://doc.nette.org/…atabase/core

ale najlepsie bude ak pouzijes Database Explorer api https://doc.nette.org/…ase/explorer ktore sa ti postara o escapovanie.

K otazke: prihlasovanie je vidno napr. v sandboxe: https://github.com/…rManager.php#L40

Editoval matopeto (18. 9. 2017 20:25)

Panthera
Člen | 20
+
0
-

Authenticator jsem již předělal na

<?php
namespace App\Model;
use Nette;
use Nette\Security as NS;

/**
 * @package App\AdminModule\Model
 */
class Authenticator extends Nette\Object implements NS\IAuthenticator{
    private $database;

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

    /**
     * @param array $credentials
     *
     * @return NS\Identity
     * @throws NS\AuthenticationException
     */
    public function authenticate(array $credentials){
        list($username, $password) = $credentials;

        $user = $this->database->fetch("SELECT * FROM users WHERE username = ?", $username);

        if(!$user) throw new NS\AuthenticateException("Uživatel '$username' nebyl nalezen.", self::IDENTITY_NOT_FOUND);

        $success = false;
        if(!$success && $user->password === md5($password)){
            $success = true;
        }

        if(!$success){
            throw new NS\AuthenticationException("Špatně zadané heslo!", self::INVALID_CREDENTIAL);
        }

        else {
            return new NS\Identity("admin", array(
                'username' => $user->username
            ));
        }
    }
}
?>

Tracy vypsala:

Call to a member function setExpiration() on null search

AuthPresenter

<?php

namespace App\AdminModule\Presenters;

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


/**
 * Class AuthPresenter
 * @package App\Presenters
 */

class AuthPresenter extends Nette\Application\UI\Presenter{

    protected function createComponentSignInForm(){
        $form = new Form;
        $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', 'Přihlásit');

        $form->onSuccess[] = [$this, 'signInFormSucceeded'];
        return $form;
    }

    public function signInFormSucceeded(Form $form, Nette\Utils\ArrayHash $values){
        try {
            $user = $this->getUser()->login($values->username,$values->password);
            $user->setExpiration('20 minutes');
            $this->redirect('Dashboard:');

        } catch (Nette\Security\AuthenticationException $e) {
            $form->addError('Nesprávné přihlašovací jméno nebo heslo.');
        }
    }
}
?>

Editoval Panthera (18. 9. 2017 20:40)

SparkCZ
Člen | 22
+
0
-

Změň

$user->setExpiration('20 minutes');

Na

$this->getUser()->setExpiration('20 minutes');

Nette\Security\User::login nevrací self

matopeto
Člen | 395
+
0
-
<?php

 $success = false;
        if(!$success && $user->password === md5($password)){
            $success = true;
        }

?>

za prve md5 vyhod a pouzi funkcie na to vstavane, vid sandox, druha vec je ze sa to da zapsat jednym riadkom

<?php
$success = $user->password === md5($password);
?>
jiri.pudil
Nette Blogger | 1028
+
0
-

První nápad: máš pro ten hash dost dlouhý databázový sloupec? Třída Passwords používá bcrypt, který produkuje hashe o délce 60 znaků

Panthera
Člen | 20
+
0
-

Toto bylo vyřešeno pomocí Vaší rady. Děkuji @SparkCZ

Pokud by jste měli další rady k zabezpečení vůči SQL INJECTION a dalším útokům, budu jen rád :)

Panthera
Člen | 20
+
0
-

@matopeto Máte tedy nápad na efektivnější řešení než md5? Rád se poučím :)

johnnie
Člen | 54
+
+1
-

Panthera napsal(a):

@matopeto Máte tedy nápad na efektivnější řešení než md5? Rád se poučím :)

Nette\Security\Passwords

Passwords::hash($password)

Sandbox UserManager

matopeto
Člen | 395
+
0
-

Panthera napsal(a):

@matopeto Máte tedy nápad na efektivnější řešení než md5? Rád se poučím :)

PHP ma vstavane funkcie na to:

http://php.net/…password.php

Nette Passwords je len wrapper, osobne by som pouzival priamo PHP funkcie.

Pokial uz mate hesla ulozene v md5 v produkcnom prostredi a chceli by ste zlepsit bezpecnost postupujte takto: https://www.michalspacek.cz/…jicich-hesel

matopeto
Člen | 395
+
+2
-

jiri.pudil napsal(a):

První nápad: máš pro ten hash dost dlouhý databázový sloupec? Třída Passwords používá bcrypt, který produkuje hashe o délce 60 znaků

Dnes je to 60 znakov v buducnosti to moze byt viac vid napr novo pridany algoritmus PASSWORD_ARGON2I v php 7.2 (https://www.zdrojak.cz/…ese-php-7-2/?…) ktory moze casom byt default preto sa odporuca pouzit na stlpec hesla aspon 255 znakovy typ.