Symfony 在 SwitchUserListener 中注入 EntityManager
Symfony inject EntityManager in SwitchUserListener
我的问题是如何在已经有 9 个参数的 SwitchUserListener 中注入实体管理器。
我有一个自定义切换用户流程,我需要在会话中设置与 _switch_user 参数 (?_switch_user=user1&external_client_id=1) 一起传递的 ExternalClient。在设置之前,我必须先从数据库中获取 ExternalClient。
我在parameters.yml中添加了
security.authentication.switchuser_listener.class: App\Bundle\Listener\SwitchUserListener
对于 App\Bundle\Listener\SwitchUserListener
的内容,我使用了 Symfony SwitchUserListener Symfony\Component\Security\Http\Firewall\SwitchUserListener.php
一切正常,当我从侦听器中的请求变量中获取 external_client_id
参数时,它被填充。但是我似乎无法访问实体管理器。
我尝试过的事情:
在services.yml
中添加装饰器
app.decorating_switch_user:
class: App\Bundle\Listener\SwitchUserListener
decorates: security.authentication.switchuser_listener
arguments: ['@app.decorating_switch_user.inner', '@doctrine.orm.entity_manager']
public: false
覆盖 services.yml
中的父依赖项
security.authentication.switchuser_listener:
abstract: true
test:
class: "%security.authentication.switchuser_listener.class%"
parent: security.authentication.switchuser_listener
public: false
# appends the '@doctrine.orm.entity_manager' argument to the parent
# argument list
arguments: ['@doctrine.orm.entity_manager']
改为监听 SwitchUserEvent
app.switch_user_listener:
class: App\Bundle\Listener\SwitchUserListener
tags:
- { name: kernel.event_listener, event: security.switch_user, method: onSwitchUser }
在这里,我将 'App\Bundle\Listener\SwitchUserListener' 的内容替换为:
class SwitchUserListener
{
public function onSwitchUser(SwitchUserEvent $event)
{
$request = $event->getRequest();
echo "<pre>";
dump($externalClientId = $request->get('external_client_id'));
echo "</pre>";
exit;
}
}
通过这次尝试,我也得到了 external_client_id,但我不知道如何注入实体管理器。即使我这样做了,我也无法获得发起 _switch_user 请求的原始用户。 SwitchUserEvent 只能访问 getTargetUser()
方法。
结论:
如果有人对此主题有经验并愿意分享,那就太好了。理想情况下,我会将实体管理器服务添加到 __construct 函数的前 9 个参数中。我正在扩展 class 就像 Matt 在这里做的那样:Symfony2: Making impersonating a user more friendly
您可以按如下方式覆盖该服务。您可能需要查看 up/change 服务参数的具体顺序,因为它在 symfony 版本之间发生了变化。一些像 $providerKey
这样的参数可以留空,因为它们会被 symfony 自动设为 changed/injected。
为了节省一些编码时间,如果您使用 setter 注入,则不需要重写构造函数。
看看 Symfony 的默认 SwitchUserListener(切换到您的应用程序中使用的 tag/version)将有助于实现您的新 handle
方法。
# app/config/services.yml
services:
# [..]
security.authentication.switchuser_listener:
class: 'Your\Namespace\SwitchUserListener'
public: false
abstract: true
arguments:
- '@security.context'
- ~
- '@security.user_checker'
- ~
- '@security.access.decision_manager'
- '@?logger'
- '_switch_user'
- ~
- '@?event_dispatcher'
- ~
calls:
- [ 'setEntityManager', [ '@doctrine.orm.entity_manager' ]]
tags:
- { name: monolog.logger, channel: security }
现在您的 SwitchUserListener 可能如下所示:
namespace Your\Namespace;
use Symfony\Component\Security\Http\Firewall\SwitchUserListener as DefaultListener;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class SwitchUserListener extends DefaultListener
{
/** @var EntityManagerInterface */
protected $em;
public function setEntityManager(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* Handles the switch to another user.
*
* @throws \LogicException if switching to a user failed
*/
public function handle(GetResponseEvent $event)
{
// Do your custom switching logic here
}
}
别忘了清除缓存!
我的问题是如何在已经有 9 个参数的 SwitchUserListener 中注入实体管理器。
我有一个自定义切换用户流程,我需要在会话中设置与 _switch_user 参数 (?_switch_user=user1&external_client_id=1) 一起传递的 ExternalClient。在设置之前,我必须先从数据库中获取 ExternalClient。
我在parameters.yml中添加了
security.authentication.switchuser_listener.class: App\Bundle\Listener\SwitchUserListener
对于 App\Bundle\Listener\SwitchUserListener
的内容,我使用了 Symfony SwitchUserListener Symfony\Component\Security\Http\Firewall\SwitchUserListener.php
一切正常,当我从侦听器中的请求变量中获取 external_client_id
参数时,它被填充。但是我似乎无法访问实体管理器。
我尝试过的事情:
在
中添加装饰器services.yml
app.decorating_switch_user: class: App\Bundle\Listener\SwitchUserListener decorates: security.authentication.switchuser_listener arguments: ['@app.decorating_switch_user.inner', '@doctrine.orm.entity_manager'] public: false
覆盖
中的父依赖项services.yml
security.authentication.switchuser_listener: abstract: true test: class: "%security.authentication.switchuser_listener.class%" parent: security.authentication.switchuser_listener public: false # appends the '@doctrine.orm.entity_manager' argument to the parent # argument list arguments: ['@doctrine.orm.entity_manager']
改为监听 SwitchUserEventapp.switch_user_listener: class: App\Bundle\Listener\SwitchUserListener tags: - { name: kernel.event_listener, event: security.switch_user, method: onSwitchUser }
在这里,我将 'App\Bundle\Listener\SwitchUserListener' 的内容替换为:
class SwitchUserListener { public function onSwitchUser(SwitchUserEvent $event) { $request = $event->getRequest(); echo "<pre>"; dump($externalClientId = $request->get('external_client_id')); echo "</pre>"; exit; } }
通过这次尝试,我也得到了 external_client_id,但我不知道如何注入实体管理器。即使我这样做了,我也无法获得发起 _switch_user 请求的原始用户。 SwitchUserEvent 只能访问
getTargetUser()
方法。
结论:
如果有人对此主题有经验并愿意分享,那就太好了。理想情况下,我会将实体管理器服务添加到 __construct 函数的前 9 个参数中。我正在扩展 class 就像 Matt 在这里做的那样:Symfony2: Making impersonating a user more friendly
您可以按如下方式覆盖该服务。您可能需要查看 up/change 服务参数的具体顺序,因为它在 symfony 版本之间发生了变化。一些像 $providerKey
这样的参数可以留空,因为它们会被 symfony 自动设为 changed/injected。
为了节省一些编码时间,如果您使用 setter 注入,则不需要重写构造函数。
看看 Symfony 的默认 SwitchUserListener(切换到您的应用程序中使用的 tag/version)将有助于实现您的新 handle
方法。
# app/config/services.yml
services:
# [..]
security.authentication.switchuser_listener:
class: 'Your\Namespace\SwitchUserListener'
public: false
abstract: true
arguments:
- '@security.context'
- ~
- '@security.user_checker'
- ~
- '@security.access.decision_manager'
- '@?logger'
- '_switch_user'
- ~
- '@?event_dispatcher'
- ~
calls:
- [ 'setEntityManager', [ '@doctrine.orm.entity_manager' ]]
tags:
- { name: monolog.logger, channel: security }
现在您的 SwitchUserListener 可能如下所示:
namespace Your\Namespace;
use Symfony\Component\Security\Http\Firewall\SwitchUserListener as DefaultListener;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class SwitchUserListener extends DefaultListener
{
/** @var EntityManagerInterface */
protected $em;
public function setEntityManager(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* Handles the switch to another user.
*
* @throws \LogicException if switching to a user failed
*/
public function handle(GetResponseEvent $event)
{
// Do your custom switching logic here
}
}
别忘了清除缓存!