Evento de control de acceso con Symfony

Quiero crear un evento que se lance antes de cargar cada página. Si tiene permiso, es decir tiene el rol adecuado puede acceder a ella, y si no que salga un mensaje de error.

Por ahora, he encontrado un ejemplo de como hacerlo al loguearse el usuario, pero lo necesito para todas las páginas de la web, ya que hay partes en las que muchos usuarios no deben acceder.

Si alguien me pudiese ayudar lo agradecería mucho, ya que he estado leyendo mucho sobre el tema pero no me queda claro como hacerlo para cualquier url de mi web.

un saludo y gracias de antemano!

Respuestas

#1

La respuesta a tu pregunta es: tienes que escuchar el evento kernel.request. En esta página se explica muy brevemente sus características. Si tienes tiempo, te recomiendo que te leas este otro artículo donde se explica con todo detalle el ciclo de vida de una petición en Symfony.

Por otra parte, y aunque me esté metiendo donde no me llaman, creo que la forma en la que estás planteando resolver este problema no es la correcta. Symfony ya te da mecanismos de control de acceso listos para usar. Para restringir grandes secciones de tu aplicación, usa la opción access_control del archivo app/config/security.yml. Para restringir las páginas con más detalle, usa la anotación @Security.

#2

Muchas gracias,

Intentaré hacerlo a través del access_control, parece mucho más sencillo.

#3

@javierguiluz, he intentado usar la opción de access_control del archivo app/config/security.yml y no me funciona.

Esto fue lo que incluí a mi archivo:

security:
  access_control:
    - { path: ^/, roles:IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https}
    #incluido esto
    - { path: ^/area-privada, roles: ROLE_X}

Por otro lado, ¿si quiero poner varios roles sería así?

- { path: ^/area-privada, roles: ROLE_X, ROLE_Y}

Muchas Gracias de nuevo.

#4

Las reglas que definas en el access_control se miran una por una y en el mismo orden que las defines. La primera regla que cumple las condiciones es la que se aplica. Por eso hay que definir en último lugar las reglas más genéricas.

En tu caso has puesto como primera regla una que afecta a cualquier URL de la aplicación (porque el path es ^/). Así que cambia el orden y pon primero las reglas más restrictivas (las que solo afectan a unas pocas URLs y no a todas):

security:
  access_control:
    - { path: ^/area-privada, roles: ROLE_X}
    - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https}

Después, para hacer que una regla se aplique a varios roles diferentes, define un array de roles, que en YAML se escribe así:

security:
  access_control:
    - { path: ^/area-privada, roles: [ROLE_X, ROLE_Y] }
    - { path: ^/, roles:IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }