我在向一些 Symfony 类添加自定义逻辑时遇到了问题。
切换用户监听器
我想添加一个检查,即用户不能切换到比初始用户拥有更多权限/角色的另一个用户。
第一次尝试
覆盖security_listeners.xml
中的参数用 key :
security.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 类并将作为私有(private)属性保存在那里,永远无法从外部访问(没有反射)。 (发生在这里:SecurityExtension.php
第 591 行)那该怎么办?定义参数两次反对 DRY。使用反射?另一点是我编写订阅者类的每次事件都会被触发。那么什么是另一个/最好的解决方案呢?
我问这个问题是因为我会遇到一些类似的问题,我想添加或覆盖一些 symfony 实习生组件。
模板猜测器
我想修改
TemplateGuesser
:对于特定的捆绑包,所有具有注释 的模板@Tempalte 模板文件应位于 Controller TestController#showAction
在这条路上:Resources/views/customDir/Test/show.html.twig
所以应该把猜测器放在一个额外的文件夹中。自定义目录 而不是只使用 浏览量 .使用
render
时具有特定模板的函数,猜测者应该忽略注释。我创建了自己的 Guesser 并覆盖了服务 ID: sensio_framework_extra.view.guesser 与
SwitchUserListener
相比这一次我的类(class)真的被称为而不是原来的猜测者。为什么它在这里有效,但不适用于 SwitchUserListener
?这是一个很好的解决方案吗?我还尝试添加第二个监听器,它调用 TemplateGuesser,它的服务 sensio_framework_extra.view.listener 与类(class)
Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener
但这没有用。
最佳答案
每当您需要添加自定义逻辑或扩展框架行为时,您都可以使用和滥用 container配置。这意味着您可以覆盖几乎所有 Symfony 定义的服务,只需创建一个扩展该服务的新类——或者不是,真的——并使用与您想要扩展或更改行为的原始服务相同的键为其创建服务定义。
例如,Symfony 有一个基础 template guesser使用 sensio_framework_extra.view.guesser
注册为服务ID。如果你想扩展它或改变行为,你只需要创建你自己的类并使用原始服务的相同 id 注册它 - 请记住,捆绑加载顺序会影响具有相同 id 的服务定义,其中最后一个加载是将被创建的那个。
那应该可以解决您的两个问题。
关于symfony - 将自定义逻辑添加到内部 Symfony 类,如 SwitchUserListener 或 TemplateGuesser,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17192294/