我正在使用Gedmo Loggable来跟踪用户对实体所做的更改。默认情况下,不会为每次更改存储用户名,但必须将其提供给侦听器。
这方面的一个例子可以在Loggable的文档中找到:
$loggableListener = new Gedmo\Loggable\LoggableListener;
$loggableListener->setAnnotationReader($cachedAnnotationReader);
$loggableListener->setUsername('admin');
$evm->addEventSubscriber($loggableListener);
这对我不起作用有两个原因:
loggableListener的方法setUsername要求字符串或带有方法getUsername的对象提供字符串。
如何将任何一个传递给侦听器?我找到了传递security_token的方法,但这还不够。我现在拥有的是:
(...)
gedmo.listener.loggable:
class: Gedmo\Loggable\LoggableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ "@annotation_reader" ] ]
#- [ setUsername, [ "A fixed value works" ] ]
- [ setUserValue, [ @security.??? ] ]
我也在使用Blameable,并为类似的问题找到了一个很好的解决方法(整个监听器被覆盖)。我试图对Loggable做同样的事情,但这看起来有点复杂。
主要问题:如何将安全用户对象(或其用户名)传递给services.yml中的侦听器?
更新
Matteo向我展示了如何将函数的结果作为参数传递给侦听器。这几乎解决了这个问题。还有另一项服务,在给定token_storage时提供用户名。但这意味着我需要将一个参数传递给一个服务,该服务作为参数提供给另一个服务。这个例子将解释:
- [ setUsername, [ "@=service('gedmo.listener.blameable').getUsername( @security.token_storage )" ] ]
现在的问题是,在此上下文中不接受@ security.token_storage。如何将参数传递给方法getUsername()?
答案 0 :(得分:1)
您可以使用Symfony Service Expressions,例如,您可以尝试以下操作:
gedmo.listener.loggable:
class: Gedmo\Loggable\LoggableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ "@annotation_reader" ] ]
- [ setUserValue, ["@=service('security.token_storage').getToken()->getUser()->getUsername()"] ]
但在某些情况下,用户可以是null
,因此您可以使用?
条件(请参阅文档)。
希望这个帮助
答案 1 :(得分:0)
我认为将authed用户注入服务是不可能的。但是您可以注入令牌存储:@security.token_storage
(在symfony 2.6之前,您必须使用@security.context
而不是@security.token_storage
)
在您的服务(LoggableListener)中,您将能够获得如下的authed用户名:
$tokenStorage->getToken()->getUser()->getUsername()
答案 2 :(得分:0)
我遇到了同样的问题,我通过创建stofDoctrineExtensionsBundle中的记录器侦听器来解决它。
为此,我创建了这个文件:
//src/AppBundle/Listener/LoggerListener
<?php
namespace AppBundle\Listener;
use Gedmo\Loggable\LoggableListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
/**
* LoggerListener
*
* @author Alexandre Tranchant <alexandre.tranchant@gmail.com>
* @author Christophe Coevoet <stof@notk.org>
*/
class LoggerListener implements EventSubscriberInterface
{
/**
* @var AuthorizationCheckerInterface
*/
private $authorizationChecker;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var LoggableListener
*/
private $loggableListener;
/**
* LoggerListener constructor.
*
* @param LoggableListener $loggableListener
* @param TokenStorageInterface|null $tokenStorage
* @param AuthorizationCheckerInterface|null $authorizationChecker
*/
public function __construct(LoggableListener $loggableListener, TokenStorageInterface $tokenStorage = null, AuthorizationCheckerInterface $authorizationChecker = null)
{
$this->loggableListener = $loggableListener;
$this->tokenStorage = $tokenStorage;
$this->authorizationChecker = $authorizationChecker;
}
/**
* Set the username from the security context by listening on core.request
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
if (null === $this->tokenStorage || null === $this->authorizationChecker) {
return;
}
$token = $this->tokenStorage->getToken();
if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
$this->loggableListener->setUsername($token);
}
}
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => 'onKernelRequest',
);
}
}
然后我在services.yml
文件中声明了这个监听器。
services:
#Loggable
gedmo.listener.loggable:
class: Gedmo\Loggable\LoggableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ "@annotation_reader" ] ]
# KernelRequest listener
app.listener.loggable:
class: AppBundle\Listener\LoggerListener
tags:
# loggable hooks user username if one is in token_storage or authorization_checker
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest}
arguments:
- '@gedmo.listener.loggable'
- '@security.token_storage'
- '@security.authorization_checker'