Hola a todos, espero me puedan ayudar.
Estoy realizando un inicio de sesión en Symfony 2.6, pero cada vez que me logueo me manda a la raíz de mi sitio (ej. http://mi_sitio.com/
).
Me he guiado por otros ejemplos y me dicen que tengo que crear un Listener, pero no tengo idea de cómo hacerlo en Symfony 2.6. Con symfony 2.1 se manejaba un archivo LoginListener que recibe otros servicios secutity.context
y router
, pero en Symfony 2.6 ya no se usa security.context
. Si me pueden ayudar aclarar mi duda. Gracias.
Respuestas
Hola, y si usas en el formulario de login un <input>
con la ruta que necesitas para dirigirte:
<input type="hidden" name="_target_path" value="/mi/ruta" />
Saludos!
@cristian_angulo
@JuniorAguilar7 como te comenta @cristian_angulo, sólo tienes que añadir un <input>
en el formulario de login o incluso puedes configurar la redirección en el propio archivo security.yml
. No necesitas crear un listener a menos que la redirección que quieras hacer sea muy avanzada (por ejemplo redirigir a cada usuario a una página diferente).
Por otra parte, en Symfony 2.6 el servicio security.context
se ha declarado obsoleto, pero todavía está disponible y puedes usarlo. Este servicio desaparecerá en Symfony 3.0 y será reemplazado por otros dos nuevos servicios: security.authorization_checker
y security.token_storage
.
@javiereguiluz
Buenas, la doc oficial explica varias formas de hacerlo:
Allí mismo tienes otras opciones interesantes, por lo que puedes probar con ellas para lograr diferentes comportamientos.
Saludos!
@manuel_j555
Muchas gracias por su ayuda. He leído la documentación pero no se qué estoy haciendo mal. Como dice Javier es lo que quiero hacer: redirigir a cada usuario a una página diferente.
# AppBundle/Resources/Config/services.yml login_listener: class: AppBundle\Listener\LoginListener arguments: ["@security.context", "@router"] tags: - { name: kernel.event_listener, event: security.interactive_login } - { name: kernel.event_listener, event: kernel.response }
// AppBundle/Listener/LoginListener.php namespace AppBundle\Listener; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Router; use Symfony\Component\Security\Core\SecurityContext; class LoginListener { private $contexto, $router, $id = null; public function __construct(SecurityContext $context, Router $router) { $this->contexto = $context; $this->router = $router; } public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) { $token = $event->getAuthenticationToken(); $this->id = $token->getUser()->getId(); } public function onKernelResponse(FilterResponseEvent $event) { if (null != $this->id) { if($this->contexto->isGranted('ROLE_ADMIN')) { $dashboard = $this->router->generate('admin_dashboard'); } else if($this->contexto->isGranted('ROLE_USER')) { $dashboard = $this->router->generate('user_dashboard'); } else if($this->contexto->isGranted('ROLE_OPERADOR')) { $dashboard = $this->router->generate('operador_dashboard'); } $event->setResponse(new RedirectResponse($dashboard)); $event->stopPropagation(); } } }
Tengo ese código y lo que pasa es que me redirige es a www.mi_sitio.com/
no me manda a las rutas que le asigno. No se qué error estoy cometiendo o qué me falta configurar.
@JuniorAguilar7
Buenas, te está faltando especificar el método a llamar en la definición del servicio, en los tags.
login_listener: class: AppBundle\Listener\LoginListener arguments: ["@security.context", "@router"] tags: - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin } - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
Me parace raro que no te de ningún error el que no coloques el method en los tags.
Saludos!
@manuel_j555
Hola @manuel_j555, ya intente lo que me dijiste, limpie cache, y aun sigue redirigiéndome a www.mi_sitio.com/
. No se qué puede estar fallando.
@JuniorAguilar7
El último else
tiene una condición, por lo que debería ser entonces else if
. Prueba a colocar unos die("Mensaje");
en alguno de los métodos para verificar si se están ejecutando o no al loguear.
@manuel_j555
Ya corregí lo del else if
. Coloqué los die()
y al parecer no entra en ningún método del listener. No veo por ningún lado los mensajes. ¿a qué se deberá esto? La opción de @cristian_angulo me sirve a la perfección, pero solo funciona para una sola ruta.
@JuniorAguilar7
Como dices que no se ejecuta ningún método, quizás el error se debe a que el servicio del login_listener
definido en el archivo AppBundle/Resources/Config/services.yml
que muestras en el comentario #4 no se está cargando.
Para confirmar o descartar este error, ejecuta el siguiente comando en la consola:
$ php app/console container:debug login_listener
Deberías ver la información de tu listener. Si no ves nada, prueba a ejecutar lo siguiente para ver todos los listener registrados en tu aplicación:
$ php app/console container:debug listener
@javiereguiluz
Muchas gracias por la ayuda a todos... @javiereguiluz ejecuté los comandos y no estaba registrado mi servicio. Lo solucioné cambiando el código que estaba en AppBundle/Resources/Config/services.yml
y lo coloque en App/config/services.yml
y funciona de maravilla muchas gracias :) (y)
@JuniorAguilar7
Ahora que ya sabemos cuál era la causa del problema, me gustaría explicar el problema con más detalle para cualquier persona que consulte esta pregunta en el futuro.
Las versiones modernas de Symfony (2.6 o superior) incluyen un archivo llamado app/config/services.yml
donde las aplicaciones pueden definir sus servicios. Cualquier servicio definido en ese archivo está disponible automáticamente en la aplicación. ¿Por qué? Porque ese archivo services.yml
se carga desde el archivo principal de configuración app/config/config.yml
.
Cuando la aplicación tiene muchos servicios, algunos programadores prefieren no usar el archivo services.yml
general y definen un archivo services.yml
(o services.xml
) en cada uno de sus bundles. Estos archivos se definen en src/NOMBRE_DEL_BUNDLE/Resources/config/
y a diferencia del archivo services.yml
global, estos archivos no se cargan automáticamente.
Cada uno de los tus bundles tiene que decirle a la aplicación que dispone de un archivo que define servicios y que quieres cargarlos. Para ello, hay que crear un archivo de tipo "extensión del contenedor de inyección de dependencias". Si el bundle se encuentra en src/Acme/MiBundle/
, hay que crear el siguiente archivo:
// src/Acme/MiBundle/DependenyInjection/AcmeMiBundleExtension.php namespace Acme\MiBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; class AcmeMiBundleExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); } }
@javiereguiluz
Muchas gracias por la información.
@JuniorAguilar7