Více autentikatoru s cookie
- Zdeno1981
- Člen | 115
Zdravím,
mám podle dokumentace vytvořený autentikator
final class Authenticator implements Nette\Security\Authenticator, Nette\Security\IdentityHandler
{
public function authenticate(string $username, string $password): SimpleIdentity
{
...
}
public function sleepIdentity(IIdentity $identity): SimpleIdentity
{
...
}
public function wakeupIdentity(IIdentity $identity): ?SimpleIdentity
{
...
}
}
V konfiguračním souboru použivám nastavení pro cookie
security:
authentication:
storage: cookie
services:
- Authenticator
Toto všechno funguje jak má až do chvíle, kdy jsem potřeboval použit druhý authenticator pro frontend modul.
Jakmile podle dokumentace použuju tuto metodu, dostanu chybu: „Call to undefined method Nette\Bridges\SecurityHttp\CookieStorage::setNamespace().“
public function checkRequirements($element): void
{
$this->getUser()->getStorage()->setNamespace('backend');
parent::checkRequirements($element);
}
Když výše zmíněnou metodu odstraním a nastavím Authenticator tímto způsobem:
services:
-
create: Authenticator
autowired: self
Tak se do aplikace sice přihlásím, ale dostanu tuto chybu „Role
‚authenticated‘ does not exist.“
Nepředá se identita, jak by měla, nejsou tam data ani role.
Nette\Security\SimpleIdentity
id: '4ca4a100353933efd7942c878523fc00'
roles: array (0)
data: array (0)
Když odstraním nastavení pro cooke a metody sleepIdentity a wakeupIdentity tak to funguje.
security:
services:
-
create: Authenticator
autowired: self
Nevím co se děje v hloubce při použití cookie s více autentikatoru, takže si s tím nevím rady, dokáže někdo poradit jak to vyřešit aby více autentikatoru fungovalo s cookie a metodami sleepIdentity a wakeupIdentity?
Editoval Zdeno1981 (14. 9. 2022 10:35)
- Marek Bartoš
- Nette Blogger | 1260
Ona tam metoda setNamespace() není, cookie storage má setCookieParameters(‚backend‘)
Ale spíš než přepínat storage bych ti doporučil mít pro administraci a veřejnou část oddělené User služby, viz https://forum.nette.org/…okie-storage#…
- Zdeno1981
- Člen | 115
@MarekBartoš
tak jsem spáchal toto, dám to sem, kdyby někdo něco podobného taky řešil, nevím jestli to je ideální řešení, ale je funkční :)
Backend modul:
securityAdmin.storage:
create: Nette\Bridges\SecurityHttp\CookieStorage
autowired: self
setup:
- setCookieParameters(name: adminLogin)
securityAdmin.authenticator:
create: App\Modules\Backend\Admin\Services\Repository\AuthRepository
autowired: self
securityAdmin.user:
create: Nette\Security\User
autowired: self
arguments:
storage: @securityAdmin.storage
authenticator: @securityAdmin.authenticator
Frontend modul kde jsem to potřeboval:
securityEfficiency.storage:
create: Nette\Bridges\SecurityHttp\CookieStorage
autowired: self
setup:
- setCookieParameters(name: efficiencyLogin)
securityEfficiency.authenticator:
create: App\Modules\Front\Efficiency\Services\Repository\EfficiencyAuth
autowired: self
securityEfficiency.user:
create: App\Modules\Front\Efficiency\Services\Domain\EfficiencyUser
arguments:
storage: @securityEfficiency.storage
authenticator: @securityEfficiency.authenticator
efficiencyPresenter:
create: App\Modules\Front\Efficiency\EfficiencyPresenter
arguments:
user: @securityEfficiency.user
Nicméně v Tracy baru není ikonka usera s identitou, ale to by neměl být problém pak doladit a přidat tam jednu ikonku pro jeden modul a druhou pro ten druhy a předat tam jednotlivé identity.
Editoval Zdeno1981 (16. 9. 2022 6:41)
- Marek Bartoš
- Nette Blogger | 1260
Když si nastavíš type ještě u securityEfficiency.user, tak ho nebudeš muset předávat manuálně
authenticator bych do Usera vůbec nepředával. Interface Authenticator vůbec nemusíš používat, stačí do User->login() předávat již ověřenou Identity
Pro custom usera můžeš Tracy panel přidat v jeho setupu. Myslím že to jde i v neonu, ale nikdy si nepamatuju jak, tak aspoň nástřel, jak by to mělo fungovat v extension:
final class CustomExtension extends \Nette\DI\CompilerExtension
{
public function loadConfiguration(): void
{
$builder = $this->getContainerBuilder();
$user = $builder->getDefinition('securityEfficiency.user');
$user->addSetup('@Tracy\Bar::addPanel', [
new \Nette\DI\Statement(\Nette\Bridges\SecurityTracy\UserPanel::class),
]);
}
}
Editoval Marek Bartoš (16. 9. 2022 7:07)
- Zdeno1981
- Člen | 115
Pokud nepředám authenticator do usera, tak se nepředává identita, sice se vytvoří cookie po spuštění sleepIdentity ale role a data jsou prázdná protože se nespustí metoda „wakeupIdentity“ koukal jsme se do Containeru co se tam děje a pokud je zápis v neonu takto:
services:
- Authenticator
Tak se do usera automaticky v conteineru předá ten authenticator, bouhžel při tomto zápisu se již automaticky nepředá do usera.
services:
-
create: Authenticator
autowired: self
ale vyzkouším tvůj návhr :)
Editoval Zdeno1981 (16. 9. 2022 8:06)
- Marek Bartoš
- Nette Blogger | 1260
Máš pravdu, Authenticator fakt musíš mít :/ sleep/wakeup by ideálně
měl být oddělený interface
https://github.com/…ty/issues/64
Editoval Marek Bartoš (16. 9. 2022 7:44)
- Zdeno1981
- Člen | 115
@MarekBartoš
S tím rozšířením jsem trochu bojoval, nemohlo mi to najít službu toho usera a navíc třída „Nette\DI\Statement“ je deprecated ale funkční řešení mám takto:
class UserAdminPanel extends CompilerExtension
{
/** @var mixed|string|null */
private mixed $panel;
public function loadConfiguration(): void
{
$builder = $this->getContainerBuilder();
$builder->addDefinition($this->prefix('panel'))
->setFactory(UserPanel::class)
->setArguments(['@securityAdmin.user']);
$this->panel = $this->getContainerBuilder()
->getByType(Bar::class);
}
public function afterCompile(ClassType $class): void
{
$init = $class->getMethods()['initialize'];
$init->addBody('$this->getService(?)->addPanel($this->getService(?));', [
$this->panel, $this->prefix('panel'),
]);
}
}
U toho modulu efficiency to mám v configu, protože nepotřebuji aby se ikonka zobrazovala u všech modulů v aplikaci.
efficiencyPresenter:
create: App\Modules\Front\Efficiency\EfficiencyPresenter
arguments:
user: @securityEfficiency.user
setup:
- @Tracy\Bar::addPanel(@securityEfficiency.userPanel)
securityEfficiency.userPanel:
create: Nette\Bridges\SecurityTracy\UserPanel(@securityEfficiency.user)
autowired: self
Akorát u modulu efficiency jsou dvě ikonky toho usera :D ale to už je detail, jinak bych musel to rozšíření odebrat a pak každému presenteru v administraci přes config předávat službu …userPanel a to se mi nechce.
Editoval Zdeno1981 (16. 9. 2022 9:53)
- Marek Bartoš
- Nette Blogger | 1260
Sorry, psal jsem to rozespalej a mám teď projekt na Nette 2.4… V Nette 3 je Statement v namespace Nette\DI\Definitions. Místo loadConfiguration() by zafungovalo beforeCompile() – pořadí provádění je loadConfiguration(), services z neonu, beforeCompile()