Cómo realizar la autenticación de usuario con el componente de seguridad de Symfony

En este artículo, aprenderás cómo configurar la autenticación de usuario en PHP usando el componente de seguridad de Symfony. Además de la autenticación, le mostraré cómo utilizar su autorización basada en roles, que puede ampliar según sus necesidades..

El componente de seguridad de Symfony

El componente de seguridad de Symfony te permite configurar funciones de seguridad como autenticación, autorización basada en roles, tokens CSRF y mucho más fácilmente. De hecho, se divide en cuatro subcomponentes que puede elegir de acuerdo con sus necesidades.

El componente de seguridad tiene los siguientes subcomponentes:

  • Symfony / Security-Core
  • symfony / security-http
  • symfony / security-csrf
  • symfony / security-acl

En este artículo, vamos a explorar la función de autenticación proporcionada por el Symfony / Security-Core componente.

Como de costumbre, comenzaremos con las instrucciones de instalación y configuración, y luego exploraremos algunos ejemplos reales para demostrar los conceptos clave.

Instalacion y configuracion

En esta sección, vamos a instalar el componente de seguridad de Symfony. Supongo que ya ha instalado Composer en su sistema; lo necesitaremos para instalar el componente de seguridad disponible en Packagist.

Así que adelante, instale el componente de seguridad con el siguiente comando.

$ compositor requiere symfony / seguridad

En nuestro ejemplo, vamos a cargar usuarios desde la base de datos MySQL, por lo que también necesitaremos una capa de abstracción de la base de datos. Instalemos una de las capas de abstracción de bases de datos más populares: Doctrine DBAL.

$ compositor requiere doctrina / dbal

Eso debería haber creado el compositor.json archivo, que debería verse así:

"require": "symfony / security": "^ 4.1", "doctrine / dbal": "^ 2.7"

Vamos a modificar el compositor.json archivo para parecerse a la siguiente.

"require": "symfony / security": "^ 4.1", "doctrine / dbal": "^ 2.7", "autoload": "psr-4": "Sfauth \\": "src" , "mapa de clase": ["src"]

Como hemos añadido un nuevo mapa de clase entrada, avancemos y actualicemos el cargador automático del compositor ejecutando el siguiente comando.

$ compositor dump -o

Ahora, puedes usar el Sfauth espacio de nombres para autocargar clases bajo la src directorio.

Así que esa es la parte de la instalación, pero ¿cómo se supone que la uses? De hecho, solo es cuestión de incluir el autoload.php archivo creado por Composer en su aplicación, como se muestra en el siguiente fragmento de código.

Un ejemplo del mundo real

En primer lugar, analicemos el flujo de autenticación habitual proporcionado por el componente de seguridad de Symfony.

  • Lo primero es recuperar las credenciales del usuario y crear un token no autenticado..
  • A continuación, pasaremos un token no autenticado al administrador de autenticación para su validación.
  • El administrador de autenticación puede contener diferentes proveedores de autenticación, y uno de ellos se utilizará para autenticar la solicitud del usuario actual. La lógica de cómo se autentica el usuario se define en el proveedor de autenticación..
  • El proveedor de autenticación se pone en contacto con el proveedor del usuario para recuperar al usuario. Es responsabilidad del proveedor del usuario cargar usuarios desde el back-end respectivo.
  • El proveedor del usuario intenta cargar al usuario utilizando las credenciales proporcionadas por el proveedor de autenticación. En la mayoría de los casos, el proveedor del usuario devuelve el objeto de usuario que implementa el Interfaz de usuario interfaz.
  • Si se encuentra el usuario, el proveedor de autenticación devuelve un token no autenticado, y puede almacenar este token para las solicitudes posteriores.

En nuestro ejemplo, vamos a hacer coincidir las credenciales del usuario con la base de datos MySQL, por lo que tendremos que crear el proveedor del usuario de la base de datos. También crearemos el proveedor de autenticación de base de datos que maneja la lógica de autenticación. Y finalmente, crearemos la clase Usuario, que implementa la Interfaz de usuario interfaz.

La clase de usuario

En esta sección, crearemos la clase de usuario que representa la entidad del usuario en el proceso de autenticación..

Sigue adelante y crea el src / User / User.php archivo con los siguientes contenidos.

username = $ username; $ this-> password = $ password; $ this-> roles = $ roles;  función pública getUsername () return $ this-> username;  función pública getPassword () return $ this-> password;  función pública getRoles () return explode (",", $ this-> roles);  public function getSalt () return "; public function eraseCredentials () 

Lo importante es que la clase Usuario debe implementar Symfony Security. Interfaz de usuario interfaz. Aparte de eso, no hay nada fuera de lo común aquí..

La clase de proveedor de base de datos

Es responsabilidad del proveedor del usuario cargar usuarios desde el back-end. En esta sección, crearemos el proveedor de usuarios de la base de datos, que carga al usuario desde la base de datos MySQL..

Vamos a crear el src / User / DatabaseUserProvider.php archivo con los siguientes contenidos.

conexión = $ conexión;  public function loadUserByUsername ($ username) return $ this-> getUser ($ username);  función privada getUser ($ username) $ sql = "SELECT * FROM sf_users WHERE username =: name"; $ stmt = $ this-> connection-> prepare ($ sql); $ stmt-> bindValue ("nombre", $ nombre de usuario); $ stmt-> execute (); $ row = $ stmt-> fetch (); if (! $ row ['username']) $ exception = new UsernameNotFoundException (sprintf ('Nombre de usuario "% s" no encontrado en la base de datos.', $ row ['username'))); $ exception-> setUsername ($ username); lanzar $ excepción;  else devolver usuario nuevo ($ fila ['nombre de usuario'], $ fila ['contraseña'], $ fila ['roles']);  función pública refreshUser (UserInterface $ user) if (! $ user instanceof User) lanzar una nueva excepción UnsupportedUserException (sprintf ('No se admiten las instancias de "% s"., get_class ($ user)));  devolver $ this-> getUser ($ user-> getUsername ());  la función pública admite Clase ($ clase) return 'Sfauth \ Usuario \ Usuario' === $ clase; 

El proveedor usuario debe implementar el UserProviderInterface interfaz. Estamos utilizando la doctrina DBAL para realizar las operaciones relacionadas con la base de datos. Como hemos implementado el UserProviderInterface interfaz, debemos implementar el loadUserByUsername, refreshUser, y apoya clase metodos.

los loadUserByUsername El método debe cargar al usuario por el nombre de usuario, y eso se hace en el getUser método. Si se encuentra el usuario, devolvemos el correspondiente Sfauth \ Usuario \ Usuario objeto, que implementa el Interfaz de usuario interfaz.

Por otro lado, la refreshUser método refresca el suministrado Usuario objeto mediante la obtención de la información más reciente de la base de datos.

Y finalmente, el apoya clase método comprueba si el DatabaseUserProvider proveedor es compatible con la clase de usuario suministrada.

La clase de proveedor de autenticación de base de datos

Finalmente, necesitamos implementar el proveedor de autenticación de usuario, que define la lógica de autenticación: cómo se autentica a un usuario. En nuestro caso, debemos hacer coincidir las credenciales del usuario con la base de datos MySQL, y por lo tanto debemos definir la lógica de autenticación en consecuencia.

Sigue adelante y crea el src / User / DatabaseAuthenticationProvider.php archivo con los siguientes contenidos.

userProvider = $ userProvider;  función protegida retrieveUser ($ username, UsernamePasswordToken $ token) $ usuario = $ token-> getUser (); if ($ user instanceof UserInterface) return $ user;  prueba $ user = $ this-> userProvider-> loadUserByUsername ($ username); if (! $ user instanceof UserInterface) arroja una nueva AuthenticationServiceException ('El proveedor del usuario debe devolver un objeto UserInterface.');  devolver $ usuario;  catch (UsernameNotFoundException $ e) $ e-> setUsername ($ username); lanzar $ e;  catch (\ Exception $ e) $ e = new AuthenticationServiceException ($ e-> getMessage (), 0, $ e); $ e-> setToken ($ token); lanzar $ e;  función protegida checkAuthentication (UserInterface $ user, UsernamePasswordToken $ token) $ currentUser = $ token-> getUser (); if ($ currentUser instanceof UserInterface) if ($ currentUser-> getPassword ()! == $ user-> getPassword ()) lanza una nueva AuthenticationException ('Las credenciales se cambiaron de otra sesión.');  else else $ password = $ token-> getCredentials (); if (vacío ($ contraseña)) arroja una nueva excepción de autenticación ('La contraseña no puede estar vacía.');  if ($ user-> getPassword ()! = md5 ($ password)) arroja una nueva AuthenticationException ('La contraseña no es válida.'); 

los DatabaseAuthenticationProvider proveedor de autenticación extiende el UserAuthenticationProvider clase abstracta. Por lo tanto, necesitamos implementar el recuperar usuario y checkAuthentication métodos abstractos.

El trabajo de la recuperar usuario El método es cargar al usuario desde el proveedor del usuario correspondiente. En nuestro caso, utilizará el DatabaseUserProvider Proveedor de usuario para cargar el usuario desde la base de datos MySQL..

Por otro lado, la checkAuthentication El método realiza las comprobaciones necesarias para autenticar al usuario actual. Tenga en cuenta que he utilizado el método MD5 para el cifrado de contraseñas. Por supuesto, debe utilizar métodos de cifrado más seguros para almacenar las contraseñas de los usuarios..

Cómo funciona en conjunto

Hasta ahora, hemos creado todos los elementos necesarios para la autenticación. En esta sección, veremos cómo ponerlo todo junto para configurar la funcionalidad de autenticación.

Sigue adelante y crea el db_auth.php Archivar y rellenar con los siguientes contenidos..

 'mysql: // USERNAME: PASSWORD @ HOSTNAME / DATABASE_NAME'), new \ Doctrine \ DBAL \ Configuration ()); // inicie nuestro proveedor de usuario de db personalizado $ userProvider = new DatabaseUserProvider ($ doctrineConnection); // usaremos UserChecker predeterminado, se usa para verificar cheques adicionales como el bloqueo / caducado de la cuenta, etc. // puede implementar su propio implementando la interfaz UserCheckerInterface $ userChecker = new UserChecker (); // inicie nuestro proveedor de autenticación de db personalizado $ dbProvider = new DatabaseAuthenticationProvider ($ userProvider, $ userChecker, 'frontend'); // administrador del proveedor de autenticación de init $ authenticationManager = new AuthenticationProviderManager (array ($ dbProvider)); intente // init un / pw, normalmente obtendrá estos de la variable $ _POST, enviados por el usuario final $ username = 'admin'; $ contraseña = 'admin'; // obtener el token no autenticado $ unauthenticatedToken = new UsernamePasswordToken ($ username, $ password, 'frontend'); // autenticar usuario y obtener el token autenticado $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken); // tenemos el token autenticado (el usuario está conectado ahora), se puede almacenar en una sesión para usar más tarde echo $ authenticatedToken; echo "\ n";  catch (AuthenticationException $ e) echo $ e-> getMessage (); echo "\ n"; 

Recuerde el flujo de autenticación que se discutió al principio de este artículo: el código anterior refleja esa secuencia.

Lo primero fue recuperar las credenciales del usuario y crear un token no autenticado..

$ unauthenticatedToken = new UsernamePasswordToken ($ username, $ password, 'frontend');

A continuación, hemos pasado ese token al administrador de autenticación para su validación.

// autenticar usuario y obtener el token autenticado $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken);

Cuando se llama al método de autenticación, muchas cosas están sucediendo detrás de escena.

En primer lugar, el administrador de autenticación selecciona un proveedor de autenticación adecuado. En nuestro caso, es el DatabaseAuthenticationProvider proveedor de autenticación, que será seleccionado para la autenticación.

A continuación, recupera al usuario por el nombre de usuario de DatabaseUserProvider Proveedor de usuarios. Finalmente, el checkAuthentication El método realiza las comprobaciones necesarias para autenticar la solicitud del usuario actual..

Si desea probar el db_auth.php guión, tendrás que crear el usuarios_f tabla en su base de datos MySQL.

CREAR TABLA 'sf_users' ('id' int (11) NOT NULL AUTO_INCREMENT, 'username' varchar (255) NOT NULL, 'password' varchar (255) NOT NULL, 'roles' enum ('registered', 'moderator', 'admin') DEFAULT NULL, PRIMARY KEY ('id')) ENGINE = InnoDB; INSERTE EN LOS VALORES 'sf_users' (1, 'admin', '21232f297a57a5a743894a0e4a801fc3', 'admin');

Sigue adelante y ejecuta el db_auth.php Guión para ver cómo va. Al finalizar con éxito, debe recibir un token autenticado, como se muestra en el siguiente fragmento de código.

$ php db_auth.php UsernamePasswordToken (usuario = "admin", authenticated = true, roles = "admin")

Una vez que el usuario se autentica, puede almacenar el token autenticado en la sesión para las solicitudes posteriores.

Y con eso, hemos completado nuestra demostración de autenticación simple!

Conclusión

Hoy, analizamos el componente de seguridad de Symfony, que te permite integrar funciones de seguridad en tus aplicaciones PHP. Específicamente, discutimos la función de autenticación provista por el subcomponente symfony / security-core, y te mostré un ejemplo de cómo esta funcionalidad se puede implementar en tu propia aplicación..

Siéntase libre de publicar sus pensamientos utilizando la siguiente alimentación!