2016-01-21 35 views
5

Używanie najnowszych Symfony i FOSUserbundle, po pomyślnym zarejestrowaniu nowego użytkownika, użytkownik jest automatycznie zalogowany. Chcę temu zapobiec. Mój powód jest taki, że tylko specjalny użytkownik powinien mieć możliwość zarejestrowania nowych użytkowników.Wyłącz automatyczne logowanie po rejestracji w FOSUserbundle Symfony

Chyba muszę zastąpić registerAction w RegisterController pakietu, ale nie wiem jak.

Próbowałem: http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_controllers.html, ale wydaje się być nieaktualne, żaden użytkownik nie jest tworzony za pomocą tej metody.

Wszelkie wskazówki są mile widziane.

Edit:

I okazało się, że nie poprawnie tworzyć wiązkę dzieci. Musiałem również stworzyć własne EventListener. Działa teraz, gdy nadpisuję zdarzenie FOSUserEvents::REGISTRATION_SUCCESS.

Dziwne jest to, że kiedy używam zdarzenie FOSUserEvents::REGISTRATION_COMPLETED, wysyłane są oba zdarzenia, mój pakiet i FOSUserbundle, tak że użytkownik jest przekierowywany do właściwej witryny, ale zalogowany jako nowy użytkownik.

Edit 2:

Tak to jest w moim słuchacza:

public static function getSubscribedEvents() 
{ 
    return array(
     FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess', 
     FOSUserEvents::REGISTRATION_COMPLETED => 'onRegistrationCompleted', 
    ); 
} 

public function onRegistrationSuccess(FormEvent $event) 
{ 
    $url = $this->router->generate('admin'); 

    $event->setResponse(new RedirectResponse($url)); 
} 

public function onRegistrationCompleted(FilterUserResponseEvent $event) 
{ 

} 

ustawić przekierowanie w przypadku REGISTRATION_SUCCESS i REGISTRATION_COMPLETED jest pusty. Za pomocą debuggera mogę sprawdzić, czy zdarzenie mojego odbiornika jest wywoływane, ale wywoływane jest także oryginalne zdarzenie.

+1

Dokumenty wyglądają dobrze. Istnieje wiele sposobów nadpisania pliku pakunków. Czy tworzysz "dziecko" użytkownika, tak jak w dokumentach? czy coś innego? Ponadto, jeśli jesteś administratorem, aby móc tworzyć użytkowników, może strona rejestru FOSuserBundle jest niewłaściwa? Z pewnością tworzenie CRUD do zarządzania użytkownikami za zaporą administratora byłoby lepsze? – DevDonkey

+0

@DevDonkey: Miałeś rację, nie udało mi się poprawnie utworzyć pakietu. Wydaje się teraz działać. Być może stworzenie CRUD byłoby łatwiejsze. – dev0

+0

fajne, cieszę się, że to załatwiłeś. – DevDonkey

Odpowiedz

0

Możesz rozwiązać ten problem za pomocą odbiornika, w pakiecie użytkownika fos, uwierzytelnia użytkownika po rejestracji.

file: friendsofsymfony/user-bundle/EventListener/AuthenticationListener.php

klasa: FOS\UserBundle\EventListener\AuthenticationListener

Jeśli zaznaczysz tej klasy można zobaczyć śledzi REGISTRATION_COMPLETED Event.

W Authenticatiton Listener Wysyła zdarzenie po wyzwoleniu funkcji logInUser. Dlatego musisz wylogować użytkownika w swoim słuchniku, który subskrybuje opcję "REJESTRACJA ZAKOŃCZONA".

można sprawdzić, czy użytkownik https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/controller_events.rst do użytkownika wylogowania.

Uwaga: Może nie być dobrym sposobem na wylogowanie użytkownika przy każdym procesie rejestracji, ale jeśli użyjesz najprościejszego sposobu i najmniejszego problemu, to jeśli już istnieje już konfiguracja yml nie istnieje , właściwie w kodzie nie ma kierunku yml conf. Tak więc takie podejście byłoby minimalne. ślad stopy.

try { 
     $this->loginManager->logInUser($this->firewallName, $event->getUser(), $event->getResponse()); 

     $eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($event->getUser(), $event->getRequest())); 
    } catch (AccountStatusException $ex) { 
     // We simply do not authenticate users which do not pass the user 
     // checker (not enabled, expired, etc.). 
    } 
+0

Nie chcę, aby użytkownik był zalogowany w pierwszej kolejności. Właśnie dlatego nadpisuję 'REGISTRATION_COMPLETED'event, w którym domyślnie uwierzytelniany jest nowy użytkownik. – dev0

+0

Czy masz na myśli, że przedłużyłeś pakiet, gdy mówisz o tym, że go zastąpiłeś? – FZE

+0

Ooops Po prostu nauczyłem się techniki nadpisywania usługi/słuchacza przez service.yml to fajne rzeczy :) http://stackoverflow.com/questions/18745087/how-to-override-fosuserbundles-emailconfirmationlistener – FZE

0

Jesteś prawie tam, jak pan powiedział twoi słuchacze są nazywane, ale tak nie jest prawidłowa, więc trzeba dokonać słuchacza być wykonywany przed domyślnie jeden Aby to zrobić zmianę

FOSUserEvents :: REGISTRATION_SUCCESS => 'onRegistrationSuccess'

do

FOSUserEvents :: REGISTRATION_SUCCESS => [ 'onRegistrationSuccess', - 10]

Zauważmy, że -10 nie zmienia się to priorytet słuchacza.

class RegistrationSuccessEventListener implements EventSubscriberInterface{ 


private $router; 

public function __construct(UrlGeneratorInterface $router){ 

     $this->router = $router; 

} 

public static function getSubscribedEvents() 
{ 
    //this will be called before 

    return array(
     FOSUserEvents::REGISTRATION_SUCCESS => ['onUserRegistrationSuccess', -30], 
    ); 

} 

/** 
* @param FormEvent $event 
* When the user registration is completed redirect 
* to the employee list page and avoid the automatic 
* mail sending and user authentication that happends 
* 
*/ 
public function onUserRegistrationSuccess(FormEvent $event){ 



    $url = $this->router->generate('employees_list'); 

    $event->setResponse(new RedirectResponse($url)); 

} 




} 

ja symfony 2.8 z wersją FOSBundle

friendsofsymfony/użytkownik wiązka dev-master 1f97ccf Symfony FOSUserBundle

według wyjściu composer info

+0

Dziękuję za odpowiedź Niestety nie mogę go przetestować teraz, ponieważ projekt został już zakończony. – dev0

0

EDYTOWANIE: Ta technika działa na Symfony 3.3, jestem nieświadomy, czy to wo rks w niższych wersjach.

Prawidłowym sposobem wykonania tej czynności jest utworzenie Compiler Pass.

Można także: Zastąpić usługę, dodając nową usługę, używając tej samej nazwy: fos_user.listener.authentication w pliku app/config.yml lub w pliku konfiguracyjnym pakunku i dodając do niej swoją nową klasę jako I ' Wykonaj poniżej i dodaj ten opis. Poniżej znajduje się sposób zastąpienia automatycznego rejestrowania podczas rejestrowania nowego użytkownika za pomocą techniki przekazywania kompilatora.

Compiler Przełęcz

namespace arpa3\UserBundle\DependencyInjection; 

use arpa3\UserBundle\EventListener\AuthenticationListener; 
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 
use Symfony\Component\DependencyInjection\ContainerBuilder; 


class OverrideServiceCompilerPass implements CompilerPassInterface { 

    public function process(ContainerBuilder $container) 
    { 
     $definition = $container->getDefinition('fos_user.listener.authentication'); 
     $definition->setClass(AuthenticationListener::class); 
    } 

} 

nadpisanie usługi

namespace arpa3\UserBundle\EventListener; 

use FOS\UserBundle\Event\FilterUserResponseEvent; 
use FOS\UserBundle\Event\UserEvent; 
use FOS\UserBundle\FOSUserEvents; 
use FOS\UserBundle\Security\LoginManagerInterface; 
use Symfony\Component\EventDispatcher\EventDispatcherInterface; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\Security\Core\Exception\AccountStatusException; 

class AuthenticationListener implements EventSubscriberInterface 
{ 
    /** 
    * @var LoginManagerInterface 
    */ 
    private $loginManager; 

    /** 
    * @var string 
    */ 
    private $firewallName; 

    /** 
    * AuthenticationListener constructor. 
    * 
    * @param LoginManagerInterface $loginManager 
    * @param string    $firewallName 
    */ 
    public function __construct(LoginManagerInterface $loginManager, $firewallName) 
    { 
     $this->loginManager = $loginManager; 
     $this->firewallName = $firewallName; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public static function getSubscribedEvents() 
    { 
     return array(
      // You can disable any of them or all of them as you want 
      //FOSUserEvents::REGISTRATION_COMPLETED => 'authenticate', 
      //FOSUserEvents::REGISTRATION_CONFIRMED => 'authenticate', 
      //FOSUserEvents::RESETTING_RESET_COMPLETED => 'authenticate', 
     ); 
    } 

    /** 
    * @param FilterUserResponseEvent $event 
    * @param string     $eventName 
    * @param EventDispatcherInterface $eventDispatcher 
    */ 
    public function authenticate(FilterUserResponseEvent $event, $eventName, EventDispatcherInterface $eventDispatcher) 
    { 
     try { 
      $this->loginManager->logInUser($this->firewallName, $event->getUser(), $event->getResponse()); 

      $eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($event->getUser(), $event->getRequest())); 
     } catch (AccountStatusException $ex) { 
      // We simply do not authenticate users which do not pass the user 
      // checker (not enabled, expired, etc.). 
     } 
    } 
} 

Zarejestruj kompilator karnet na głównym pliku pęczka

namespace arpa3\UserBundle; 

use arpa3\UserBundle\DependencyInjection\OverrideServiceCompilerPass; 
use Symfony\Component\HttpKernel\Bundle\Bundle; 
use Symfony\Component\DependencyInjection\ContainerBuilder; 

class arpa3UserBundle extends Bundle { 

    public function getParent() { 

     return 'FOSUserBundle'; 
    } 

    /** 
    * 
    * This injects a Compiler Pass that is used to override the automatic login after registration of a new user 
    * We have done this in order to disable the "by default" behaviour given that only admins can register users 
    * and logging in into the newly created account automatically is just not a desired behaviour 
    * 
    * @param ContainerBuilder $container 
    */ 
    public function build (ContainerBuilder $container) { 

     parent ::build($container); 

     $container -> addCompilerPass(new OverrideServiceCompilerPass()); 

    } 

} 

Istnieją inne sposoby, takie jak przesłonięcie usługi uwierzytelniania w pliku config.yml, ale powyższe rozwiązanie jest najczystszym i najbardziej konserwowanym rozwiązaniem, jakie znalazłem.