5

我在向一些 Symfony 类添加自定义逻辑时遇到了问题。

切换用户监听器

我想添加一个检查,即用户不能切换到比初始用户拥有更多权限/角色的另一个用户。

第一次尝试

用密钥覆盖中的参数security_listeners.xmlsecurity.authentication.switchuser_listener.class但是我在哪里可以覆盖它呢?
在 security.yml 中它不起作用:

security:
    ...
    authentication:
        switchuser_listener:
             class:  Symfony\Component\Security\Http\Firewall\SwitchUserListener

第二次尝试

覆盖 SwitchUserListner 服务 id 的服务:security.authentication.switchuser_listener

我在我的包的 service.xml 中创建了相同的服务,但我的类没有被使用/调用。

另一个想法是只覆盖类,但这仅适用于捆绑包,但 SwitchUserListener 不在 SecurityBundle 中,它在 symfony 组件目录中,在我看来,覆盖 SecurityBundle 是一个非常糟糕的主意

第三次尝试

现在我得到了解决方案:第一次我没有意识到调度程序调用了 SwitchUserListener 中的 SWTICH_USER 事件的侦听器:

$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);

所以我只需要为这个事件类型创建一个带有特殊标签的服务:

<tag name="kernel.event_listener" event="security.switch_user" method="onSecuritySwitchUser" />

并在给定的方法中进行检查。

这似乎是比其他两个更好的解决方案。但是还有一个问题。在我的 SwitchUserEvent 监听器中,如果用户想要退出切换的用户,我需要忽略我的自定义检查。所以我需要检查请求的路径:ignore if path containts '?switch_user=_exit'
但是路径(URL参数)可以改变:

# app/config/security.yml
security:
    firewalls:
        main:
            # ...
            switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }

但是在我的包中我无法读取这个参数,因为它不会被传递给service container. 它将被传递给SwitchUserListner类的构造函数,并将作为私有属性保存在那里,永远不能从外部访问(没有反射)。(发生在这里:SecurityExtension.php第 591 行)那该怎么办?定义参数两次反对 DRY。使用反射?

另一点是我编写订阅者类的每次事件都会被触发。那么什么是另一个/最好的解决方案呢?
我问这个问题是因为我会遇到一些类似的问题,我想添加或覆盖一些 symfony 实习生组件。

模板猜测器

我想修改TemplateGuesser:对于一个特定的包,所有具有注释@Tempalte的模板都应该与控制器一起TestController#showAction位于此路径:

Resources/views/customDir/Test/show.html.twig

所以猜测者应该被放置并将所有内容定位到一个额外的文件夹customDir而不是只使用views。当使用render带有特定模板的函数时,猜测者应该忽略注释。

我创建了自己的 Guesser 并覆盖了服务 ID:sensio_framework_extra.view.guesser,与SwitchUserListener这次相比,我的课程真正被调用而不是原来的guesser。为什么它在这里有效,但不适用于SwitchUserListener?

这是一个很好的解决方案吗?我还尝试添加第二个侦听器,它调用 TemplateGuesser,它的服务sensio_framework_extra.view.listener与类Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener但这没有用。

4

1 回答 1

0

每当您需要添加自定义逻辑或扩展框架行为时,您都可以使用和滥用容器配置。这意味着您可以覆盖几乎所有 Symfony 定义的服务,只需创建一个扩展该服务的新类——或者不是,真的——并使用与您想要扩展或更改行为的原始服务相同的键为其创建服务定义。

例如,Symfony 有一个基本模板猜测器注册为具有sensio_framework_extra.view.guesserid 的服务。如果你想扩展它或改变行为,你只需要创建你自己的类并使用原始服务的相同 id 注册它 - 请记住,捆绑加载顺序会影响具有相同 id 的服务定义,其中最后一个加载是将被创建的那个。

那应该可以解决您的两个问题。

于 2014-06-18T15:01:06.233 回答