Escenario
Una aplicación symfony 4.4 con el framework Sonata Admin 3.78.1 cuenta con una página de login para que los administradores del sitio puedan gestionar sus clientes. Ahora queremos que los clientes puedan usar la misma página de login para acceder a sus datos personales como, por ejemplo, sus facturas. Para la gestión de usuarios la aplicación utiliza los paquetes friendsofsymfony/user-bundle 2.1.2 y sonata-project/user-bundle 4.9.0Problema
En config/packages/security.yaml se puede configurar el comportamiento de la aplicación tras un login exitoso, en el bloque de firewall.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
firewalls: # Disabling the security for the web debug toolbar, the profiler and Assetic. dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false # -> custom firewall for the admin area of the URL admin: pattern: /admin(.*) context: user switch_user: true form_login: provider: fos_userbundle login_path: /admin/login use_forward: false check_path: /admin/login_check failure_path: null use_referer: true default_target_path: sonata_admin_dashboard |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php namespace Acme\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sonata\AdminBundle\Action\DashboardAction; /** * Description of DefaultController * * @author marcos */ class DefaultController extends Controller { /** * * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function defaultRoute() { if ($this->get('security.authorization_checker')->isGranted('ROLE_CUSTOMER')) { return $this->redirectToRoute('admin_acme_customer_profile'); } $dashboardAction = $this->container->get(DashboardAction::class); $currentRequest = $this->container->get('request_stack')->getCurrentRequest(); return $dashboardAction($currentRequest); } } |
1 2 3 4 5 6 7 8 9 10 11 |
role_hierarchy: ROLE_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN] ROLE_SUPER_ADMIN: - ROLE_ADMIN - ROLE_ALLOWED_TO_SWITCH ROLE_CUSTOMER: [ROLE_USER] ... access_control: # Admin login page needs to be accessed without credential - { path: ^/admin/default, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/customer/*, role: [ROLE_ADMIN, ROLE_CUSTOMER] } |
Solución
El problema es que por defecto la acción de Sonata Admin (definida en Sonata\UserBundle\Action\LoginAction es dirigir al usuario a la ruta sonata_admin_dashboard. Una manera de solucionarlo es declarar esa ruta en config/routes.yaml para que dirija al controlador de antes que comprueba el rol del usuario:
1 2 3 |
sonata_admin_dashboard: path: /admin/dashboard controller: Acme\Controller\DefaultController::defaultRoute |