¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Symfony 5
  3. Seguridad en una aplicación Symfony
Extrait - Symfony 5 Desarrolle sitios web PHP estructurados y eficientes
Extractos del libro
Symfony 5 Desarrolle sitios web PHP estructurados y eficientes Volver a la página de compra del libro

Seguridad en una aplicación Symfony

Descripción general y conceptos de seguridad

1. Los desafíos de la seguridad de las aplicaciones web

A medida que se añaden ciertas funcionalidades cuando se desarrolla un sitio web, como una zona de «miembros» o una de administración, la cuestión de la seguridad se convierte rápidamente en una preocupación importante.

Symfony divide en dos etapas el proceso por el que el acceso a un recurso está restringido a un número limitado de usuarios: autenticación y autorización.

La primera etapa, la autenticación, consiste en identificar a un usuario. Una vez identificado el usuario, la aplicación se encarga de comprobar si el usuario está autorizado para acceder al recurso o para realizar la acción solicitada.

A nivel del protocolo HTTP, estos dos conceptos se ilustran en particular por los estados 401 y 403. El estado 401 significa que se requiere autenticación para acceder al recurso. Por otro lado, el estado 403 indica que el servidor ha identificado correctamente al usuario, pero este no está autorizado para acceder al recurso.

2. Seguridad en Symfony

SecurityBundle gestiona la seguridad. Está integrado en la aplicación de forma predeterminada si ha creado el proyecto a partir del esqueleto de la aplicación web. De lo contrario, es posible añadirlo con la siguiente recipe:

composer require symfony/security-bundle 

Las directivas...

Autenticación

1. Cortafuegos

La función del firewall o cortafuegos consiste en definir las zonas de la aplicación sujetas al sistema de seguridad.

Cuando la petición de un usuario coincide con las reglas definidas por un firewall, se habilita la seguridad. Por lo tanto, la petición debe pasar a través de este firewall y satisfacer las restricciones en términos de permisos especificadas en él.

Una petición se asocia a un firewall en función de su ruta (path). Volvamos a la sección firewalls de nuestra configuración básica:

# config/packages/security.yaml   
   
security:   
   
 # ...   
   
 firewalls:   
   mi_firewall:   
     pattern:    ^/   
     anonymous: ~ 

Aquí definimos un firewall llamado mi_firewall. La directiva pattern contiene la expresión regular que se aplicará a la ruta de la consulta para determinar si debe pasar a través del firewall o no. Dado que todas las rutas de acceso deben comenzar con un slash, la expresión regular anterior hace que todas las peticiones pasen por el firewall mi_firewall.

La directiva anonymous establece que los usuarios anónimos (no autenticados) pueden acceder a este firewall. Por lo tanto, la aplicación no es segura; todas las páginas son de libre acceso.

Firewall para un subdominio

Además del path, el firewall puede analizar el nombre de dominio de la consulta. Esto se hace con la directiva host:

host:   
 pattern:    ^/   
 host:       mi-sección\.ejemplo\.com   
 http_basic: ~ 

Aquí, el nombre de dominio mi-sección.ejemplo.com requiere autenticación HTTP. Volveremos sobre esta técnica más adelante en este capítulo.

Firewall para recursos estáticos/de desarrollo

Algunas rutas siempre deben ser accesibles. En particular, este es el caso de los recursos estáticos (imágenes, hojas de estilo, etc.) o las URL utilizadas internamente por Symfony (como la barra de depuración del Profiler).

Para evitar proteger inadvertidamente este tipo de recurso, le recomendamos...

Usuarios y roles

1. El usuario

Con Symfony, el objeto que representa a un usuario debe implementar obligatoriamente la interfaz Symfony\Component\Security\Core\User\UserInterface, que proporciona los siguientes métodos:

  • getUsername(), que devuelve el nombre de usuario.

  • getPassword(), que devuelve la contraseña del usuario.

  • getSalt(), que devuelve el valor del salt de la contraseña (volveremos más adelante en este capítulo sobre este concepto, con los encoders).

  • getRoles(), que devuelve los roles del usuario. Estos roles afectan al nivel de permisos de cada miembro. En la práctica, permiten, por ejemplo, decir si el miembro es un administrador, un moderador o un simple usuario.

  • eraseCredentials(), que el framework utiliza internamente. Este método borra la información confidencial (si la hay) contenida en el objeto usuario. Es útil si, por ejemplo, en un momento dado la contraseña se almacena en formato de texto abierto en el objeto.

Dependiendo del proveedor de usuarios que elija o cree, los objetos que representan a los usuarios pueden implementar una clase más completa que UserInterface: Symfony\Component\Security\Core\User\AdvancedUserInterface. El objetivo de este último es admitir las características de suspensión y expiración de las cuentas de usuario.

a. Recuperar el usuario actual

Para recuperar el usuario autenticado actualmente, dispone del acceso directo getUser() en sus controladores:

<?php  
namespace App\Controller;   
   
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 
use Symfony\Component\HttpFoundation\Request;  
use Symfony\Component\HttpFoundation\Response;  
use Symfony\Component\Routing\Annotation\Route;  
   
class DefaultController extends AbstractController   
{   
   /**   
    * @Route("/")   
    */   
   public function index()   
   {   
       $usuario = $this->getUser();   
       // ...   
   }   
} 

Si el usuario está autenticado, el método devuelve...

Permisos

Hasta ahora, hemos aprendido cómo autenticar a los usuarios a través de diferentes métodos y diferentes proveedores de usuario. Conocemos la representación de un usuario y sabemos que tiene roles. Ahora veremos cómo asignar seguridad a los recursos.

1. Los roles en el centro del proceso

El principio de autorización es sencillo: los usuarios tienen roles y el acceso a ciertos recursos se puede limitar a ciertos roles. Por lo tanto, los roles son elementos fundamentales del proceso de autorización. Antes de continuar, es necesario que le presentemos nuevos roles.

Si un usuario está detrás de uno de los firewalls que ha definido (en config/packages/security.yaml), debe tener, al menos, uno de los roles siguientes:

  • IS_AUTHENTICATED_ANONYMOUSLY: el usuario no está autenticado (está detrás de un firewall que permite usuarios anónimos).

  • IS_AUTHENTICATED_REMEMBERED: el usuario se autentica a través de la función «recordarme».

  • IS_AUTHENTICATED_FULLY: el usuario se ha autenticado en la petición o sesión actual.

No tiene que gestionar estos roles en el método getRoles() de su objeto de usuario porque Symfony los genera automáticamente.

2. Comprobar el rol de usuario

Para asignar seguridad a cualquiera de sus acciones, nunca debe confiar en los roles devueltos por el objeto usuario. Por ejemplo, los roles que acabamos de presentar (IS_AUTHENTICATED_*) no están presentes a nivel del objeto usuario porque Symfony utiliza internamente un token para verificar una autorización. 

A continuación, se indica cómo verificar que se ha concedido un rol determinado al usuario actual:

<?php  
namespace App\Controller;   
  
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 
use Symfony\Component\HttpFoundation\Request;  
use Symfony\Component\HttpFoundation\Response;  
use Symfony\Component\Routing\Annotation\Route;  
   
class DefaultController extends AbstractController   
{    
   /**    
    * @Route("/")    
    */...