我正在Symfony2中构建自己的用户管理系统(不使用FOSUserBundle),并且希望能够强制用户更改密码。
我已经设置了一个EventListener来监听kernal.request
事件,然后我在监听器中执行一些逻辑来确定用户是否需要更改密码;如果他们这样做,那么他们将被重定向到更改密码"路由。
我将服务添加到config.yml
以收听kernal.request
:
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 / profiler bar /任何其他内部控制器的事件?或者是将用户重定向到change_password页面的更好方法(不仅仅是登录成功)?
疯狂地思考疯狂的黑客解决方案,但是在Symfony2中肯定有办法优雅地处理这个问题吗?
答案 0 :(得分:1)
这是我现在使用的非常黑客的解决方案:
dev
环境这就是使这项工作变得疯狂的原因:
// 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;
}