2013-10-17 6 views
5

Ich baue mein eigenes Benutzerverwaltungssystem in Symfony2 (nicht mit FOSUserBundle) und möchte Benutzer zwingen, ihr Passwort zu ändern.Symfony2 - Redirect Antwort von Anforderung EventListener im Dev-Modus beim Ignorieren von eingebauten Anfrageereignissen

Ich habe einen EventListener eingerichtet, um das kernal.request Ereignis zu hören, dann führe ich einige Logik im Listener durch, um festzustellen, ob der Benutzer sein Passwort ändern muss; Wenn dies der Fall ist, werden sie zu einer Route "Passwort ändern" weitergeleitet.

füge ich den Dienst meiner config.yml auf dem kernal.request zu hören:

password_change_listener: 
    class: Acme\AdminBundle\EventListener\PasswordChangeListener 
     arguments: [ @service_container ] 
     tags: 
      - { name: kernel.event_listener, event: kernel.request, method: onMustChangepasswordEvent } 

Und dann der Zuhörer:

public function onMustChangepasswordEvent(GetResponseEvent $event) { 

    $securityContext = $this->container->get('security.context'); 

    // if not logged in, no need to change password 
    if (!$securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) 
    return; 

    // If already on the change_password page, no need to change password 
    $changePasswordRoute = 'change_password'; 
    $_route = $event->getRequest()->get('_route'); 
    if ($changePasswordRoute == $_route) 
    return; 

    // Check the user object to see if user needs to change password 
    $user = $this->getUser(); 
    if (!$user->getMustChangePassword()) 
    return; 

    // If still here, redirect to the change password page 
    $url = $this->container->get('router')->generate($changePasswordRoute); 
    $response = new RedirectResponse($url); 
    $event->setResponse($response); 
} 

Das Problem, das ich habe ist, dass in den Entwicklermodus, meine Zuhörer Außerdem werden die Profiler-Leiste und die Assestic-Request-Ereignisse umgeleitet. Es funktioniert, wenn ich Assets auslagere und den Cache lösche und die Site im Produktionsmodus betrachte.

Gibt es eine Möglichkeit, die Ereignisse von Assite/Profiler Bar/andere interne Controller ignorieren? Oder eine bessere Möglichkeit, einen Benutzer auf die Seite change_password umzuleiten (nicht nur bei erfolgreichem Login)?

Verrückt denken, wilde Hack-Lösungen, aber es gibt sicherlich einen Weg, dies elegant in Symfony2 zu behandeln?

Antwort

0

Dies ist die Hack Lösung, die ich jetzt bin mit:

  • Wenn ja, bekommt ein Array aller Routen
  • Filter die Route Array, so dass nur

    1. fest, ob in dev Umgebung die Routen, die ich hinzugefügt habe, bleiben
    2. Vergleichen Sie die aktuelle Route mit dem Array von Routen
    3. Wenn eine Übereinstimmung gefunden wird, bedeutet dies, dass das Ereignis kein integrierter Controller ist, sondern ein tha sein muss t habe ich hinzugefügt, also führe die Weiterleitung durch.

    Und das ist der Wahnsinn, dass die Arbeit macht:

    // determine if in dev environment 
    if (($this->container->getParameter('kernel.environment') == 'dev')) 
    { 
    
        // Get array of all routes that are not built in 
        // (i.e You have added them yourself in a routing.yml file). 
        // Then get the current route, and check if it exists in the array 
        $myAppName = 'Acme'; 
        $routes = $this->getAllNonInternalRoutes($myAppName); 
        $currentRoute = $event->getRequest()->get('_route'); 
        if(!in_array($currentRoute, $routes)) 
        return; 
    } 
    
    // If still here, success, you have ignored the assetic and 
    // web profiler actions, and any other actions that you did not add 
    // yourself in a routing.yml file! Go ahead and redirect! 
    $url = $this->container->get('router')->generate('change_password_route'); 
    $response = new RedirectResponse($url); 
    $event->setResponse($response); 
    

    Und die verrückt Hack Funktion getAllNonInternalRoutes(), die es (das macht Arbeit eine Modifikation des Codes I here by Qoop gefunden:

    private function getAllNonInternalRoutes($app_name) { 
    
        $router = $this->container->get('router'); 
        $collection = $router->getRouteCollection(); 
        $allRoutes = $collection->all(); 
    
        $routes = array(); 
    
        foreach ($allRoutes as $route => $params) 
        { 
        $defaults = $params->getDefaults(); 
    
        if (isset($defaults['_controller'])) 
        { 
         $controllerAction = explode(':', $defaults['_controller']); 
         $controller = $controllerAction[0]; 
    
         if ((strpos($controller, $app_name) === 0)) 
         $routes[]= $route; 
        } 
        } 
        return $routes; 
    }