通过Silex SecurityServiceProvider注销后显示消息

时间:2013-06-02 14:47:01

标签: events silex

我正在使用 SecurityServiceProvider 保护我的Silex应用程序,并希望在用户通过导航到 logout_path 路由退出后显示消息。

消息应存储在会话闪存包中,以便我的模板可以在之后自动显示。

我尝试过添加应用程序中间件,但是无法挂钩我的代码。之前的挂钩似乎不起作用,因为它发生在安全性之后,因此在安全性重定向回我的主页之后。

使用 Application :: EARLY_EVENT 的前钩子似乎要早,因为据我所知,安全提供程序在注销后会破坏会话。

在我继续尝试寻找一种有效但可能很脏的解决方案之前,我想问一下这个案例最好/最干净的解决方案是什么?

更新:在npms提示注销事件处理程序之后,我在Google上找到了this article,它描述了如何很好地解决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消息不再存在。因此,在执行注销成功处理程序后,会话似乎被销毁了......或者我错过了什么?这甚至是正确的方法吗?

更新:尚未找到合适的解决方案。但这很有效。

我已在注销的目标网址中添加了一个参数,并使用它来检测是否已注销。

$app->register( new SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'default' => array(
            'pattern'=> '/user',
            'logout' => array(
                'logout_path' => '/user/logout',
                'target_url' => '/?logout'
            ),
        )
    )
));

1 个答案:

答案 0 :(得分:2)

我有同样的问题,你的想法引导我找到解决方案,谢谢!

首先在 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

(已编码)以提示 / goodbye 对话框中的任何消息。