Las cookies nos permiten ofrecer nuestros servicios. Al utilizar nuestros servicios, aceptas el uso que hacemos de las cookies. Más Información. Aceptar

Symfony2 Tutorial: Seguridad y acceso

Sergio Yamuza
  • Escrito por Sergio Yamuza el 29 de Octubre de 2015
  • 4 min de lectura | Backend
Symfony2 Tutorial: Seguridad y acceso

El sistema de seguridad de Symfony tiene como objetivo determinar qué usuarios tienen acceso a determinados recursos de la aplicación. Este proceso se realiza en dos fases: autenticación y autorización.

Firewalls (Autenticación)

El sistema obliga al usuario a enviar algún tipo de identificación con el objetivo de identificarlo en el sistema.

Control de acceso (Autorización)

Una vez autenticado, el sistema debe determinar si dicho usuario tiene acceso al recurso que ha solictado comprobando sus privilegios.

Este proceso se realiza a través del componente Security de Symfony, que también está disponible como librería PHP independiente y, por tanto, puede utilizarse en cualquier otro proyecto PHP.

Cabe destacar que, en una aplicación Symfony, siempre hay un usuario logueado técnicamente hablando, conocido como usuario anónimo.

Anonymous user

Autenticación HTTP

Es el método más básico para controlar la seguridad. Consiste en definir las rutas que queremos proteger en nuestra aplicación y el usuario debe autenticarse utilizando la típica ventana de login generada por el navegador, indicando su nombre de usuario y contraseña.

El archivo en el que se configura la seguridad de la aplicacion es /app/config/security.yml

security:
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            pattern:    ^/
            anonymous: ~
            http_basic:
                realm: "Admin"

    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }

    providers:
        in_memory:
            memory:
                users:
                    user:  { password: userpass, roles: 'ROLE_USER' }
                    admin: { password: adminpass, roles: 'ROLE_ADMIN' }

    encoders:
        Symfony\Component\Security\Core\User\User: plaintext

¿Qué cambios se han realizado?

Se ha configurado un nuevo firewall llamado main . Donde pattern establece una expresión regular para activarlo en todas las rutas de la aplicación, permitiendo el acceso de usuarios anónimos y con el método HTTP para manejar la autenticación.

El apartado access_control sirve para definir los privilegios necesarios para acceder a las rutas que queremos proteger. En este caso necesitamos proteger todas las rutas cuyo patrón empiece por /admin , con lo que obligamos al usuario a autenticarse a la hora de acceder al panel de administración de EasyAdminBundle que instalamos en el capítulo anterior. Además, el único role permitido es ROLE_ADMIN .

La sección providers establece de qué modo carga Symfony la información de un usuario. La forma más sencilla es definir los usuarios y sus roles directamente en el archivo de seguridad. Se pueden definir varios providers y configurar cuál de ellos se utiliza en cada uno de los firewall que tengamos.

En encoders se define el tipo de encriptación de la contraseña. Al definir el provider in_memory podemos utilizar el objeto Symfony\Component\Security\Core\User\User sin codificación, es decir, en texto plano.

<div style=“text-align:center;margin-top:20px;margin-bottom:20px;” markdown=“1”> Anonymous user </div>

Al introducir el nombre y contraseña del usuario con ROLE_ADMIN la aplicación recarga la página y podemos acceder al contenido. Si volvemos a mirar la barra de debug, podemos ver cómo ahora el usuario admin está logueado en la aplicación. Pinchando en este apartado podemos ampliar la información.

<div style=“text-align:center;margin-top:20px;margin-bottom:20px;” markdown=“1”> Anonymous user </div>

Si un usuario con ROLE_USER se loguea e intenta acceder a /admin el componente de seguridad devolverá una cabecera HTTP con error 403 forbidden : acceso no permitido. Por ello, es imprescindible crear nuestras proprias vistas de error y poder mostrar a los usuarios mensajes personalizados y enlazarlos a otras rutas.

En la documentación podemos aprender a cómo personalizar las páginas de error .

Otras formas de autenticación

Symfony permite otras formas de autenticación más avanzadas, que implementan más seguridad y son visualmente más atractivas para el usuario.

BCrypt Password Encoder

Se trata de utilizar una codicicación de la contraseña en lugar de utilizar una en texto plano como vimos anteriormente. La configuración es la siguiente:

encoders:
   Symfony\Component\Security\Core\User\User:
       algorithm: bcrypt
       cost:      12

Las contraseñas de los usuarios deben indicarse ahora codificadas

providers:
    in_memory:
        memory:
            users:
              user:
                  password: $2a$12$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli
                  roles: 'ROLE_USER'
              admin:
                  password: $2a$12$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G
                  roles: 'ROLE_ADMIN'

Para codificar una contraseña en bcrypt puedes utilizar esta herramienta online .

Formulario de acceso

Este método es más amigable para el usuario, ya que podemos crear un formulario incluyendo todos los campos que necesitemos obtener y pudiendo darle un aspecto visual más atractivo.

En la documentación del CookBook puedes encontrar cómo construir el típico formulario de login pero, si te fijas, lo primero que nos sugieren es utilizar FOSUserBundle , que proporciona una gestión completa de los usuarios de nuestra aplicación.

La clave de la modularización de librerías es precisamente esta, reutilizar todo el código que sea posible. Entonces, ¿por qué reinventar la rueda?. ´FOSUserBundle´ es uno de lo bundles más utilizados en la comunidad Symfony, estable y con una documentación muy buena.

Definición de Roles de usuario

Los roles son la clave del proceso de autorización. Un usuario puede tener uno o varios de ellos. Se definen como cadenas de texto aunque internamente se manejan como objetos.

Puedes crear tantos roles como necesites simplemente definiéndolos en el apartado role_hierarchy . Para que sean procesados automáticamente por Symfony su nombre debe comenzar por ROLE_ .

También se puede defininr una jerarquía de roles, para que un rol pueda a su vez contener otros. Un ejemplo:

ROLE_ADMIN:       ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

ROLE_SUPER_ADMIN contiene un array de roles: Uno llamado ROLE_ADMIN , cuyo valor es ROLE_USER . El otro, ROLE_ALLOWED_TO_SWITCH , permite al usuario logueado cambiar de usuario y autenticarse con otra cuenta.

Seguridad en controladores y vistas

Para denegar el acceso en un controlador:

<?php

public function indexAction()
{
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'No puede acceder a esta página!');
}

De esta forma, cualquier usuario que no tenga el role ROLE_ADMIN se le mostrará el mensaje indicado en el tercer parámetro del método.

Para controlar si un usuario está logueado sin tener en cuenta los roles:

<?php

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

Para controlar el acceso en las vistas:

{% if is_granted('ROLE_ADMIN') %}
    <a href="...">Eliminar</a>
{% endif %}

Si se utiliza esta regla en una url que no esté cubierta por un firewall Symfony lanzará un error. Por eso es una buena práctica definir un firewall principal que contemple todas las url de la aplicación, como hicimos en el ejemplo de autenticación HTTP: pattern: ^/ .

Estas son algunas de las empresas que ya confían en OpenWebinars

Profesores y profesionales

Nuestros docentes son profesionales que trabajan día a día en la materia que imparten

Conviértete en profesor de OpenWebinars