2013-10-17 6 views
5

Symfony2 (FOSUserBundle을 사용하지 않음)에서 내 자신의 사용자 관리 시스템을 구축 중이며 강제로 사용자가 비밀번호를 변경하도록하고 싶습니다.Symfony2 - 내장 된 요청 이벤트를 무시하면서 dev 모드에서 요청 EventListener의 응답 리디렉션

kernal.request 이벤트를 수신하도록 EventListener를 설정 한 다음 수신기에서 사용자가 암호를 변경해야하는지 여부를 결정하기 위해 일부 논리를 수행합니다. 암호가 변경되면 "암호 변경"경로로 리디렉션됩니다.

은 내가 kernal.request에서 수신하도록 내 config.yml에 서비스를 추가 :

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

그리고 청취자 :

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); 
} 

오전 데 문제가 개발자 모드에서, 내 청취자가 있다는 것이다 또한 프로파일 바 및 assetic 요청 이벤트를 리디렉션합니다. 애셋을 덤프하고 캐시를 지우고 프로덕션 모드에서 사이트를 볼 때 작동합니다.

assetic/profiler bar/다른 내부 컨트롤러의 이벤트를 무시할 수있는 방법이 있습니까? 또는 사용자를 change_password 페이지로 리디렉션하는 더 좋은 방법입니다 (로그인 성공뿐만 아니라)?

야생 해킹 솔루션을 생각해 보려고하지만 Symfony2에서이를 우아하게 처리 할 수있는 방법이 있습니까?

답변

0

이것은 매우 해킹 내가 지금 사용하고 솔루션입니다 :

  1. dev 환경
  2. 그렇다면에,
  3. 필터 경로 배열 있도록 모든 경로의 배열을 얻을 수 있는지 확인 만 내가 추가 한 경로가 남아 있습니다
  4. 현재 경로를 경로 배열과 비교하십시오.
  5. 일치하는 것이 발견되면 이벤트가 내장 컨트롤러가 아니며 그 중 하나 여야 함을 의미합니다 내가 추가 했으므로 리디렉션을 수행하십시오.

그리고이 것을 만드는 미친 짓 작업 :

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; 
} 
: 그것은 내가 here by Qoop을 발견 코드의 수정 인 (작동하게

// 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); 

그리고 미친 해킹 기능 getAllNonInternalRoutes()