Editační systém – ověření přihlášení
- Panthera
- Člen | 20
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
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
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
Změň
$user->setExpiration('20 minutes');
Na
$this->getUser()->setExpiration('20 minutes');
Nette\Security\User::login nevrací self
- jiri.pudil
- Nette Blogger | 1028
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ů
- johnnie
- Člen | 54
Panthera napsal(a):
@matopeto Máte tedy nápad na efektivnější řešení než md5? Rád se poučím :)
Passwords::hash($password)
- matopeto
- Člen | 395
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:
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
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.