2012-07-16 18 views

Respuesta

27

Una forma de resolver esto es usar un detector de eventos en el evento security.interactive_login. En este caso, simplemente conecto otro oyente en ese oyente de eventos para que se active la respuesta. Esto permite que la autenticación aún suceda, pero aún realizar una redirección una vez completa.

<service id="sotb_core.listener.login" class="SOTB\CoreBundle\EventListener\SecurityListener" scope="request"> 
    <tag name="kernel.event_listener" event="security.interactive_login" method="onSecurityInteractiveLogin"/> 
    <argument type="service" id="router"/> 
    <argument type="service" id="security.context"/> 
    <argument type="service" id="event_dispatcher"/> 
</service> 

Y la clase ...

class SecurityListener 
{ 
    protected $router; 
    protected $security; 
    protected $dispatcher; 

    public function __construct(Router $router, SecurityContext $security, EventDispatcher $dispatcher) 
    { 
     $this->router = $router; 
     $this->security = $security; 
     $this->dispatcher = $dispatcher; 
    } 

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) 
    { 
     $this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse')); 
    } 

    public function onKernelResponse(FilterResponseEvent $event) 
    { 
     if ($this->security->isGranted('ROLE_TEAM')) { 
      $response = new RedirectResponse($this->router->generate('team_homepage')); 
     } elseif ($this->security->isGranted('ROLE_VENDOR')) { 
      $response = new RedirectResponse($this->router->generate('vendor_homepage')); 
     } else { 
      $response = new RedirectResponse($this->router->generate('homepage')); 
     } 

     $event->setResponse($response); 
    } 
} 
+0

buen trabajo, simple oyente de eventos! – pregmatch

+0

¡perfecto! Nota rápida.No tuve que definir scope = request al registrar escucha (symfony2 v 2.4.8). –

2

Si está buscando una respuesta simple que @MDrollette, se puede poner un bloque de redirección similares en el controlador de la página de conexión tiene éxito.

4

Utilicé la respuesta de Mdrollette pero esta solución tiene un gran inconveniente, usted anula completamente la respuesta original de Symfony y al hacerlo elimina la cookie recordarme que Symfony configuró en el encabezado.

mi solución era cambiar la OnKernelResponse esta manera:

public function onKernelResponse(FilterResponseEvent $event) 
{ 
    if ($this->security->isGranted('ROLE_TEAM')) { 
     $event->getResponse()->headers->set('Location', $this->router->generate('team_homepage'));  
    } elseif ($this->security->isGranted('ROLE_VENDOR')) { 
     $event->getResponse()->headers->set('Location', $this->router->generate('vendor_homepage')); 
    } else { 
     $event->getResponse()->headers->set('Location', $this->router->generate('homepage')); 
    } 
} 

De esta manera usted sigue siendo el Recuérdamela cookie intacta.

0

Por el bien de las pruebas, si quiere preservar la respuesta original también puede copiar los encabezados. El método de clonación en el objeto Redirigir solo copia los encabezados.

public function onKernelResponse(FilterResponseEvent $event) 
{ 
    if ($this->security->isGranted('ROLE_TEAM')) { 
     $response = new RedirectResponse($this->router->generate('team_homepage')); 
    } elseif ($this->security->isGranted('ROLE_VENDOR')) { 
     $response = new RedirectResponse($this->router->generate('vendor_homepage')); 
    } else { 
     $response = new RedirectResponse($this->router->generate('homepage')); 
    } 

    $response->headers = $response->headers + $event->getResponse()->headers; 

    $event->setResponse($response); 
} 
+0

Aparece el error 'Aviso: el objeto de la clase Symfony \ Component \ HttpFoundation \ ResponseHeaderBag no se pudo convertir a int', ¿tal vez por el operador +? – Permana

9

Para Symfony> = 2.6 ahora sería:

<?php 

namespace CommonBundle\Listener; 

use Monolog\Logger; 
use Symfony\Component\EventDispatcher\EventDispatcherInterface; 
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 
use Symfony\Component\Routing\Router; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; 

class LoginListener 
{ 
    /** @var Router */ 
    protected $router; 

    /** @var TokenStorage */ 
    protected $token; 

    /** @var EventDispatcherInterface */ 
    protected $dispatcher; 

    /** @var Logger */ 
    protected $logger; 

    /** 
    * @param Router $router 
    * @param TokenStorage $token 
    * @param EventDispatcherInterface $dispatcher 
    * @param Logger $logger 
    */ 
    public function __construct(Router $router, TokenStorage $token, EventDispatcherInterface $dispatcher, Logger $logger) 
    { 
     $this->router  = $router; 
     $this->token  = $token; 
     $this->dispatcher = $dispatcher; 
     $this->logger  = $logger; 
    } 

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) 
    { 
     $this->dispatcher->addListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']); 
    } 

    public function onKernelResponse(FilterResponseEvent $event) 
    { 
     $roles = $this->token->getToken()->getRoles(); 

     $rolesTab = array_map(function($role){ 
      return $role->getRole(); 
     }, $roles); 

     $this->logger->info(var_export($rolesTab, true)); 

     if (in_array('ROLE_ADMIN', $rolesTab) || in_array('ROLE_SUPER_ADMIN', $rolesTab)) { 
      $route = $this->router->generate('backend_homepage'); 
     } elseif (in_array('ROLE_CLIENT', $rolesTab)) { 
      $route = $this->router->generate('frontend_homepage'); 
     } else { 
      $route = $this->router->generate('portal_homepage'); 
     } 

     $event->getResponse()->headers->set('Location', $route); 
    } 
} 

Y services.yml

services: 
common.listener.login: 
    class: CommonBundle\Listener\LoginListener 
    arguments: [@router, @security.token_storage, @event_dispatcher, @logger] 
    scope: request 
    tags: 
     - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin } 
3

Probado en Symfony 3,1

También podría establecer ruta predeterminada después del inicio de sesión del usuario con éxito para todos los usuarios en el archivo seciurity.yml así:

[config/seciurity.yml]

... 

firewalls: 
    # disables authentication for assets and the profiler, adapt it according to your needs 
    dev: 
     pattern: ^/(_(profiler|wdt)|css|images|js)/ 
     security: false 
    main: 
     pattern: /.* 
     form_login: 
      login_path: /login 
      check_path: /login_check 
      default_target_path: /login/redirect <<<<<<<<<<<<<<<<<<<<<<<<< 
     logout: 
      path: /logout 
      target:/
     security: true 
     anonymous: ~ 
... 

y luego en ese lugar hacer redirección sencilla basada en rol de usuario. Muy directo. Algunos dicen que la mejor manera es siempre la mejor. Usted decide :)

[SomeBundle/Controlador/SomeController.php]

/** 
* Redirect users after login based on the granted ROLE 
* @Route("/login/redirect", name="_login_redirect") 
*/ 
public function loginRedirectAction(Request $request) 
{ 

    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) 
    { 
     return $this->redirectToRoute('_login'); 
     // throw $this->createAccessDeniedException(); 
    } 

    if($this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) 
    { 
     return $this->redirectToRoute('_admin_panel'); 
    } 
    else if($this->get('security.authorization_checker')->isGranted('ROLE_USER')) 
    { 
     return $this->redirectToRoute('_user_panel'); 
    } 
    else 
    { 
     return $this->redirectToRoute('_login'); 
    } 

} 

funciona como un encanto, pero tener en cuenta para comprobar siempre para papeles más restringidas a la baja en caso de que su ROLE_ADMIN también tiene privilegios de ROLE_USER y más ...

+0

+1 ¡Gran enfoque! En función de su configuración, es posible que también deba agregar la opción 'always_use_default_target_path: true'. – conceptdeluxe

Cuestiones relacionadas