0

我目前正在开发自定义逻辑模拟侦听器。

我覆盖了 Symfony\Component\Security\Http\Firewall\SwitchUserListener 因为我想在授权切换事件之前调用一些实体存储库(不是用户实体):

例如,当且仅当要模拟的用户已经向请求切换的用户授予权限时,我才想授权切换。

是否可以将新参数(例如教义服务或某些数组值)注入覆盖的侦听器?

对我的自定义 SwitchUserListenener 的调用:

in services.yml

parameters:
    security.authentication.switchuser_listener.class: acme\appBundle\EventListener\SwitchUserListener
4

1 回答 1

0

您的解决方案可能在这里:
https ://github.com/symfony/symfony/blob/2.6/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php#L597

security.authentication.switchuser_listenerSymfony 定义的服务是一个抽象服务。它实际上不是用作侦听器的服务,而是同一个类。

在代码中向上一点:
https ://github.com/symfony/symfony/blob/2.6/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php#L233

foreach ($firewalls as $name => $firewall) {
    list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds);

这是您创建的可以进行用户切换的防火墙的名称。

现在您有几个选项可以覆盖侦听器。你可以继续覆盖类参数,然后像 Symfony 一样操作参数:

$listener->replaceArgument(1, new Reference($userProvider));
$listener->replaceArgument(3, $id);
$listener->replaceArgument(6, $config['parameter']);
$listener->replaceArgument(7, $config['role']);

或者更简单地说,在你的扩展中编译额外的方法调用。

另一种解决方案是创建一个CompilerPass系统地删除原始侦听器并用您自己的侦听器替换它们的解决方案。如果在SecurityBundle.

$container->removeDefinition($id);

编辑:

另一个可能比上面更简单的解决方案是创建另一个事件侦听器。一个根据请求触发的。这里重要的是,侦听器必须比您要覆盖的侦听器具有更高的优先级(我使用了侦听器,因为可能有多个切换用户侦听器)。

棘手的部分将是获取被覆盖的侦听器 ID 的列表,因为您将需要遍历它们并调用您自己的方法来在侦听器被实例化之后但在它们触发之前注入您的新依赖项。

于 2014-12-04T14:28:40.583 回答