我正在使用 SecurityServiceProvider 来保护我的 Silex 应用程序的安全,并希望在用户通过导航到 logout_path 路由注销后显示一条消息。
消息应该存储在 session 闪存包中,以便我的模板可以在之后自动显示它。
我尝试添加应用程序中间件,但无法 Hook 我的代码。之前 Hook 似乎不起作用,因为它发生在安全之后,因此在安全重定向回我的主页之后。
Application::EARLY_EVENT 的 before 钩子(Hook)似乎为时过早,因为据我所知,安全提供程序会在注销后销毁 session 。
在我继续尝试找到一种可行但可能肮脏的解决方案之前,我想问一下对于这种情况最好/最干净的解决方案是什么?
更新:在 npms 提示注销事件处理程序后,我发现 this article在 Google 上,它描述了如何很好地解决 Symfony 中的问题。
在 Silex 中,情况略有不同,在阅读了 SecurityServiceProvider 的源代码后,我想出了这个解决方案。
$app['security.authentication.logout_handler._proto'] = $app->protect(function ($name, $options) use ($app) {
return $app->share(function () use ($name, $options, $app) {
return new CustomLogoutSuccessHandler(
$app['security.http_utils'],
isset($options['target_url']) ? $options['target_url'] : '/'
);
});
});
class CustomLogoutSuccessHanler extends DefaultLogoutSuccessHandler {
public function onLogoutSuccess(Request $request)
{
$request->getSession()->getFlashBag()->add('info', "Logout success!");
return $this->httpUtils->createRedirectResponse($request, $this->targetUrl);
}
}
但问题是,重定向后 flashbag 消息不再存在。所以看来在执行注销成功处理程序后 session 正在被销毁......或者我错过了什么?这是正确的方法吗?
更新:仍然没有找到合适的解决方案。但这是有效的。
我在注销的目标 URL 中添加了一个参数,并使用它来检测是否进行了注销。
$app->register( new SecurityServiceProvider(), array(
'security.firewalls' => array(
'default' => array(
'pattern'=> '/user',
'logout' => array(
'logout_path' => '/user/logout',
'target_url' => '/?logout'
),
)
)
));
最佳答案
我也遇到了同样的问题,您的想法让我找到了解决方案,谢谢!
首先在security.firewall中定义注销:
$app->register(new Silex\Provider\SecurityServiceProvider(), array(
'security.firewalls' => array(
'general' => array(
'logout' => array(
'logout_path' => '/admin/logout',
'target_url' => '/goodbye'
)
)
),
));
创建一个CustomLogoutSuccessHandler,用于处理注销所需的GET参数,在本例中为重定向、消息和 pid:
class CustomLogoutSuccessHandler extends DefaultLogoutSuccessHandler
{
public function onLogoutSuccess(Request $request)
{
// use another target?
$target = $request->query->get('redirect', $this->targetUrl);
$parameter = array();
if (null != ($pid = $request->query->get('pid'))) {
$parameter['pid'] = $pid;
}
if (null != ($message = $request->query->get('message'))) {
$parameter['message'] = $message;
}
$parameter_str = !empty($parameter) ? '?'.http_build_query($parameter) : '';
return $this->httpUtils->createRedirectResponse($request, $target.$parameter_str);
}
}
注册处理程序:
$app['security.authentication.logout_handler.general'] = $app->share(function () use ($app) {
return new CustomLogoutSuccessHandler(
$app['security.http_utils'], '/goodbye');
});
使其按预期工作的技巧是使用另一条注销路线:
$app->get('/logout', function() use($app) {
$pid = $app['request']->query->get('pid');
$message = $app['request']->query->get('message');
$redirect = $app['request']->query->get('redirect');
return $app->redirect(FRAMEWORK_URL."/admin/logout?pid=$pid&message=$message&redirect=$redirect");
});
/logout设置需要的参数并执行定时注销/admin/logout
现在您可以使用
/logout?redirect=anywhere
注销后重定向到任何其他路由或
/logout?message=xyz
(编码)在/再见对话框中提示任何消息。
关于events - 通过 Silex SecurityServiceProvider 注销后显示消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16883849/