Aprende cómo iniciar sesión / autenticar a un usuario manualmente desde tu controlador en Symfony 3.

Herramientas como FOSUserBundle facilitan mucho las cosas cuando hablamos de manipulación de usuarios, formularios de inicio de sesión y registro, etc., ¿quién no puede negarse a eso? Probablemente aquellos que necesitan tener todo bajo control y entender cómo funciona esto. Es por eso que algunos desarrolladores, incluso si no usan FOSUserBundle, prefieren manejar esos eventos manualmente.

¿Está buscando iniciar sesión como usuario con su propio código de un controlador? Ha encontrado el lugar adecuado para aprenderlo. En este artículo, aprenderá cómo iniciar sesión como usuario automáticamente en su aplicación Symfony (con o sin credenciales).

Cómo hacerlo

Lo primero que debe hacer es importar algunas clases a saber InteractiveLoginEventUsernamePasswordTokenen su controlador. Luego, busque su usuario usted mismo utilizando el administrador de entidades de Doctrine o, alternativamente, use el administrador de usuarios de FOSUserBundle. El usuario debe almacenarse en una variable y representará una instancia de  FOS\UserBundle\Model\Useren caso de que esté usando FOSUser o simplemente User si no lo hace. A continuación, proceda a crear un token y configurarlo en el servicio de almacenamiento de tokens. La clase para crear el token espera como primer argumento el objeto de usuario, ya que el segundo argumento suele ser la contraseña del usuario, sin embargo, puede ser nulo. Como tercer argumento, debe proporcionar el nombre del cortafuegos que se utilizará, mainsin embargo , por lo general, vale la pena verificar susecurity.ymlarchivo en caso de que tenga otro nombre. Como cuarto argumento, debe proporcionar los roles del usuario.

También debe almacenar el token generado por la clase en la sesión y finalmente enviar el evento de inicio de sesión interactivo manualmente:

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;

class SomeController extends Controller
{
    public function loginAction(Request $request)
    {
        $user = /*El usuario necesita estar registrado. */;#
        // Ejemplo de cómo obtener un usuario:
        //$user = $this->getDoctrine()->getManager()->getRepository("AppBundle/Entity/User")->findOneBy(array('username' => "some user name example"));
        
        // Manejar la obtención o creación de la entidad de usuario probablemente con un formulario publicado
        // El tercer parámetro "principal" puede cambiar según el nombre de su firewall en security.yml
        $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
        $this->get('security.token_storage')->setToken($token);

        // Si el nombre del firewall no es principal, entonces el valor establecido sería en su lugar:
        // $this->get('session')->set('_security_XXXFIREWALLNAMEXXX', serialize($token));
        $this->get('session')->set('_security_main', serialize($token));
        
        // Activar el evento de inicio de sesión manualmente
        $event = new InteractiveLoginEvent($request, $token);
        $this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
        
        /*
         * Ahora el usuario está autenticado !!!!
         * Haga lo que necesita hacer ahora, como renderizar una vista, redirigir a la ruta, etc.
         */
    }
}

Hecho esto, ha registrado automáticamente un usuario en la sesión, sin embargo, no verificó las credenciales del usuario.

Ejemplo de controlador de inicio de sesión personalizado

Supongamos que está creando algún formulario de inicio de sesión personalizado (o anulando el formulario de inicio de sesión predeterminado de FOSUserBundle) y necesita autenticar a su usuario manualmente. Para esto, el primer ejemplo de controlador funcionaría solo para configurar el usuario en la sesión, sin embargo, no se está autenticando realmente ya que no estamos verificando ni el nombre de usuario ni la contraseña.

Lo primero que debemos hacer antes de configurar un usuario en la sesión, es verificar si las credenciales que dio son correctas. Para hacer esto, necesitamos el servicio de codificación de seguridad en nuestro controlador para verificar la autenticidad de los datos proporcionados. En este ejemplo te vamos a mostrar con lógica básica cómo funciona el proceso de autenticación:

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;

class SomeController extends Controller
{
    public function loginAction(Request $request)
    {
        // Es más probable que estos datos se recuperen incluso del objeto Solicitud (del formulario)
        // Pero para que sea fácil de entender ...
        $_username = "batman";
        $_password = "batmobil";

        // Recuperar el codificador de seguridad de Symfony
        $factory = $this->get('security.encoder_factory');

        /// Iniciar recuperación de usuario
        // Recuperemos al usuario por su nombre de usuario:
        // Si está utilizando FOSUserBundle:
        $user_manager = $this->get('fos_user.user_manager');
        $user = $user_manager->findUserByUsername($_username);
        // O por ti mismo
        $user = $this->getDoctrine()->getManager()->getRepository("userBundle:User")
                ->findOneBy(array('username' => $_username));
        /// Usuario de recuperación final

        // ¡Compruebe si el usuario existe!
        if(!$user){
            return new Response(
                'Username doesnt exists',
                Response::HTTP_UNAUTHORIZED,
                array('Content-type' => 'application/json')
            );
        }

        /// Iniciar verificación
        $encoder = $factory->getEncoder($user);
        $salt = $user->getSalt();

        if(!$encoder->isPasswordValid($user->getPassword(), $_password, $salt)) {
            return new Response(
                'Username or Password not valid.',
                Response::HTTP_UNAUTHORIZED,
                array('Content-type' => 'application/json')
            );
        } 
        /// Fin verificación 

        // ¡La contraseña coincide! luego proceda a configurar el usuario en sesión
        
        // Manejar la obtención o creación de la entidad de usuario probablemente con un formulario publicado
        // El tercer parámetro "principal" puede cambiar según el nombre de su firewall en security.yml
        $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
        $this->get('security.token_storage')->setToken($token);

        // Si el nombre del firewall no es principal, entonces el valor establecido sería en su lugar:
        // $this->get('session')->set('_security_XXXFIREWALLNAMEXXX', serialize($token));
        $this->get('session')->set('_security_main', serialize($token));
        
        // Activar el evento de inicio de sesión manualmente
        $event = new InteractiveLoginEvent($request, $token);
        $this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
        
        /*
         * Ahora el usuario está autenticado !!!!
         * Haga lo que necesita hacer ahora, como renderizar una vista, redirigir a la ruta, etc.
         */
        return new Response(
            'Welcome '. $user->getUsername(),
            Response::HTTP_OK,
            array('Content-type' => 'application/json')
        );
    }
}

Que te diviertas ❤️!


Ingeniero de Software Senior en EPAM Anywhere. Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores