Chyba při přihlašování do administrace

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

Ahoj, mám v nette dva moduly a u každého řeším samostatné přihlašování. Při přihlášení mi laděnka vrátí chybu Authenticator has not been set. myslím si že mám chybu někde v configu tak bych se chtěl zeptat jak na to.

Authenticator:

public function authenticate(array $credentials)
	{
		list($email, $password) = $credentials;

		$user = $this->usersManagerAdmin->findOneBy(['username' => $email]);

		if (!$user) {
			throw new AuthenticationException('Byl zadaný špatný e-mail.', self::IDENTITY_NOT_FOUND);

		} elseif (!Passwords::verify($password, $user->password)) {
			throw new AuthenticationException('Bylo zadané špatné heslo..', self::INVALID_CREDENTIAL);

		} elseif (Passwords::needsRehash($user->password)) {
			$user->setPassword(Passwords::hash($password));
			$this->em->persist($email);
			$this->em->flush();
		}

		return $user;
	}

Přihlašovací presenter:

public function proccessLogIn(Form $form, $values)
    {
        $user = $this->getUser();
        $user->getStorage()->setNamespace('Admin');
        $user->login($values->email, $values->password);
        $this->redirect('Admin:Homepage:login');
        $this->flashMessage('Vítejte v administraci '.$_SERVER['HTTP_HOST'], 'success');
    }

BassePresenter:

public function getUser() {
        $user = parent::getUser();
        $user->getStorage()->setNamespace('Admin');
        return $user;
    }

a config:

services:
    - App\AdminModule\Model\Security\UsersManagerAdmin

    adminAuthenticator:
            class: App\AdminModule\Model\Security\AdminAuthenticator
            autowired: no

Díky za každou ranu už si stím fakt nevím rady..

Aurielle
Člen | 1281
+
0
-

Budeš si muset authenticator v přihlašovacím presenteru ručně vytáhnout z kontejneru (teoreticky by mohl jít i injectnout, vyzkoušej, nemám otestované) a nastavit do Usera, nebo zrušit příznak autowired: no. Což ale předpokládám nechceš, protože máš pravděpodobně authenticatory dva.

Hitny14
Člen | 90
+
0
-

Mohl by jsi mi to prosím tě nějak víc vysvětlit? Nevím jestli si ten athenticator vytukuju správně stačí to takhle?

$this->context->AdminAuthenticator

A vbec nevím co myslíš tím „nstavit do usera“?

Unlink
Člen | 298
+
+1
-

Určite nič nevyťahuj z contextu, radšej si ho tam injectni

Prihlasovací presenter

function __construct(AdminAuthenticator $authentificator) {
	$this->authentificator = $authentificator;
}

public function proccessLogIn(Form $form, $values)
{
    $user = $this->getUser();
	$user->setAuthenticator($this->authentificator); //Nastaviť ho userovi
    $user->getStorage()->setNamespace('Admin');
    $user->login($values->email, $values->password);
    $this->redirect('Admin:Homepage:login');
    $this->flashMessage('Vítejte v administraci '.$_SERVER['HTTP_HOST'], 'success');
}

A potom si ten presenter zaregistruj v configu, aby si mu vedel predať ten authentificator

services:
    - App\Moj\Login\Presenter(@App\AdminModule\Model\Security\AdminAuthenticator)
Jan Suchánek
Člen | 404
+
0
-

@Unlink: a co takhle?

function __construct(AdminUserManager $adminUserManager) {
    $this->adminUserManager = $adminUserManager;
}

public function proccessLogIn(Form $form, $values)
{
    // $user = $this->getUser(); // Nepotřebuju, o usera se stará manager.
    // $user->setAuthenticator($this->authenticator); // Service dostane authenticator
    // $user->getStorage()->setNamespace('Admin'); Service se stará o namespace, nebo možná by stačil jen ten authenticator

    try {
    	$this->adminUserManager->login($values->email, $values->password);
    	$this->flashMessage('Vítejte v administraci!', 'success'); // fujky $_SERVER['HTTP_HOST'] na to používáme něco jiného ne?
    } catch(Nette\Security\AuthenticationException $e){ // použít vlastní excepiton nebo Nette\Security\AuthenticationException
		$form->addError($e->getMessage()); // buď vypsat co se stalo případně si napsat vlastní chybu
		return;
	}
	$this->restoreRequest($this->backlink);
	$this->redirect('Admin:Homepage:');
}

převzato z CD-collection.

Editoval jenicek (2. 6. 2015 13:03)

David Matějka
Moderator | 6445
+
+2
-

@jenicek v cd-collection se vola login na Nette\Security\User a to pak zavola authenticator

tri rozumny moznosti, co me napadaji:

  1. to, jak to pise @Unlink
  2. Nette\Security\User::login muze rovnou akceptovat jako parametr identitu, takze pujde i
$identity = $this->adminUserManager->authenticate(array($email, $password));
$this->user->login($identity);

to by se nechalo pak trochu refaktorovat, ze by pouziti vypadalo ± tak, jak pise @jenicek
3. trochu slozitejsi, ale nejhezci :) Vytvoris si jeste jeden authenticator, ktery bude routovat pozadavky na konkretni authenticatory dle nastavenyho namespace na user storage. Tenhle princip pouzivam v librette/security-namespaces, zjednodusene by to mohlo vypadat nejak takto:

class AuthenticatorRouter extends Nette\Object implements Nette\Security\IAuthenticator
{

	private $authenticators = [];

	private $userStorage;

	public function __construct(Nette\Security\IUserStorage $userStorage)
	{
		$this->userStorage = $userStorage;
	}

	public function add($namespace, Nette\Security\IAuthenticator $authenticator)
	{
		$this->authenticators[$namespace] = $authenticator;
	}

	public function authenticate(array $credentials)
	{
		$ns = $this->userStorage->getNamespace();
		if (!isset($this->authenticators[$ns])) {
			throw new \Exception;
		}
		return $this->authenticators[$ns]->authenticatoe($credentials);
	}
}
services:
	frontAuthenticator: {class: FrontAuthenticator, autowired: false}
	adminAuthenticator: {class: AdminAuthenticator, autowired: false}
	authenticator:
		class: AuthenticatorRouter
		setup:
			- add(Admin, @adminAuthenticator)
			- add(Front, @frontAuthenticator)

v sign presenteru pak staci nastavit spravny NS na user storage a pojede to :)

Jan Suchánek
Člen | 404
+
0
-

@David Matějka za mě tam chyběl blok try, a ukončení v případě chyby, navíc by to furt vítalo.

A $_SERVER[‚HTTP_HOST‘] tam fakt patří?

Editoval jenicek (2. 6. 2015 14:29)

Hitny14
Člen | 90
+
0
-

Díky všem za odpovědi. Použil sem příklad od @Unlink a při nastavení v configu:

services:
    - App\AdminModule\Model\Security\UsersManagerAdmin
    - App\AdminModule\Presenters\Homepage\HomepagePresenter(@App\AdminModule\Model\Security\AdminAuthenticator)
    adminAuthenticator:
            class: App\AdminModule\Model\Security\AdminAuthenticator
            autowired: no

Mi to hlási chybu:
Class App\AdminModule\Presenters\Homepage\HomepagePresenter used in service ‚78_App_AdminModule_Presenters_Homepage_HomepagePresenter‘ not found or is not instantiable.

Přihlašování používám v HomepagePresenteru.

@DavidMatějka ještě bych se chtěl prosím tě zeptat kdybych chtěl použít ten tvůj třetí způsob kam bych mel dát ten AuthenticatorRouter? Do App/Models/Security a nebo do App/AdminModule/Models/Security

David Matějka
Moderator | 6445
+
0
-

@Hitny14 spise do toho App/Models/Security

Unlink
Člen | 298
+
0
-

@Hitny14 máš tam zlý namespace, App\AdminModule\Presenters\Homepage\HomepagePresenter má byť namespace nie cesta k tomu presenteru

Hitny14
Člen | 90
+
0
-

@DavidMatějka chtěl sem zkusit ten tvůj třetí způsob a laděnak mi hlási chybu že authenticator nebyl nalezen.
Class App\Model\Security\Authenticator used in service ‚authenticator‘ not found or is not instantiable.

Takhle vypadá můj authenticator:

<?php

namespace App\Model\Security;

use Nette\Object;
use Nette\Security\IAuthenticator;

/**
 * Class Authenticator
 * @package App\Model\Security
 */
abstract class Authenticator extends Object implements IAuthenticator
{
    private $authenticators = [];

    private $userStorage;

    public function  __construct(Nette\Security\IUserStorage $userStorage) {
        $this->userStorage = $userStorage;
    }

    public function add($namespace, Nette\Security\IAuthenticator $authenticator) {
        $this->authenticators[$namespace] = $authenticator;
    }

    public function authenticator(array $credentials) {
        $ns = $this->userStorage->getNamespace();
        if(!isset($this->authenticators[$ns])) {
            throw new \Exception;
        }
        return $this->authenticators[$ns]->authenticate($credentials);
    }
}

Začínám i s doctrínou je to možná použiti i pro doctrinu?

A můj config:

- App\Model\Security\Users
    frontAuthenticator: {class: App\Model\Security\FrontAuthenticator, autowired: false}
    adminAuthenticator: {class: App\AdminModule\Model\Security\AdminAuthenticator, autowired: false}
    authenticator:
        class: App\Model\Security\Authenticator
        setup:
            - add(Admin, @adminAuthenticator)
            - add(Front, @frontAuthenticator)
David Matějka
Moderator | 6445
+
0
-

ta trida nema byt abstraktni (a ta metoda ma byt authenticate a ne authenticator)

Hitny14
Člen | 90
+
0
-

Moje chyba špatně sem si toho všiml. Všechno je v pohodě ale jen když se chci přihlásit. Tak mě laděnka vyzívá k definování metody
Call to undefined method App\AdminModule\Model\Security\AdminAuthenticator::authenticator()

To nestačí když mám v configu:

frontAuthenticator: {class: App\Model\Security\FrontAuthenticator, autowired: false}
    adminAuthenticator: {class: App\AdminModule\Model\Security\AdminAuthenticator, autowired: false}
    authenticator:
        class: App\Model\Security\AuthenticatorRoute
        setup:
            - add(Admin, @adminAuthenticator)
            - add(Front, @frontAuthenticator)
Hitny14
Člen | 90
+
0
-

Chyba opravena.

public function authenticator(array $credentials) {
        $ns = $this->userStorage->getNamespace();
        if(!isset($this->authenticators[$ns])) {
            throw new \Exception;
        }
        return $this->authenticators[$ns]->authenticator($credentials);
    }

v části

	return $this->authenticators[$ns]->authenticator($credentials);

má být:

	return $this->authenticators[$ns]->authenticate($credentials);
David Matějka
Moderator | 6445
+
0
-

chybka :) diky, opravil jsem to v puvodni ukazce