2013-10-17 4 views
5

要求イベントに建て無視してDEVモードでの要求のEventListenerからの応答をリダイレクトします。Symfony2のは - 私はSymfony2の(FOSUserBundleを使用していない)に自分のユーザー管理システムを構築し、自分のパスワードを変更するようユーザーに強制することができるようにしたいのです

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

私が午前問題は、DEVモードでは、私のリスナーがあるということですプロファイラバーとassays要求イベントのリダイレクトも行います。アセットをダンプしてキャッシュをクリアし、サイトを運用モードで表示すると機能します。

私はassetic /プロファイラバー/その他の内部のコントローラからのイベントを無視することができる方法はありますか?または、ユーザーをchange_passwordページにリダイレクトするより良い方法(ログインの成功だけでなく)?

狂った思考アップ野生のハックソリューションを行く、しかし確実にSymfony2の中でエレガントにこれを処理する方法はありますか?

答えて

0

は、これは非常にハック、私は今のところ使用していますソリューションです:

  1. dev環境
  2. その場合には、
  3. フィルタールートアレーように、すべてのルートの配列を取得かどうかを確認するだけ私が追加したルートは残っています
  4. 現在のルートのルートとの比較
  5. これが見つかると、イベントは内蔵コントローラではなく、私は追加したので、リダイレクトを実行します。

そして、これは仕事ということになり狂気です:

// 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()は(私はhere by Qoopが見つかりました:

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