Symfony2:注入@security.context以获取当前用户。如何避免一个“错误”;ServiceCircularReferenceException;?注入整个容器?
在解决问题之后,我遇到了另一个问题/安全问题/问题 正如您在另一篇文章中看到的,我试图在侦听器中注入安全上下文,但如果我不碰代码,就不动代码,则会出现以下错误: ServiceCircularReferenceException:检测到的循环引用 服务“条令.orm.default\u实体\u管理器” 因此,通过阅读和研究,我找到了一个解决方案,但我不清楚我的应用程序是否正确或安全。这就是我所做的: 我没有注入Symfony2:注入@security.context以获取当前用户。如何避免一个“错误”;ServiceCircularReferenceException;?注入整个容器?,security,symfony,dependency-injection,doctrine-orm,Security,Symfony,Dependency Injection,Doctrine Orm,在解决问题之后,我遇到了另一个问题/安全问题/问题 正如您在另一篇文章中看到的,我试图在侦听器中注入安全上下文,但如果我不碰代码,就不动代码,则会出现以下错误: ServiceCircularReferenceException:检测到的循环引用 服务“条令.orm.default\u实体\u管理器” 因此,通过阅读和研究,我找到了一个解决方案,但我不清楚我的应用程序是否正确或安全。这就是我所做的: 我没有注入[@security.context]而是这样做: services: ord
[@security.context]
而是这样做:
services:
orderhascomment.listener:
class: PL\OrderBundle\Listener\OrderHasCommentListener
arguments: [@service_container]
tags:
- { name: doctrine.event_listener, event: prePersist, method: onPrePersist }
我的listenerOrderHasCommentListener.php
如下所示:
namespace PL\OrderBundle\Listener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerInterface;
class OrderHasCommentListener {
protected $container;
public function __construct(ContainerInterface $container = null) {
$this->container = $container;
}
/**
*
* @param LifecycleEventArgs $args
*/
public function onPrePersist(LifecycleEventArgs $args) {
$entity = $args->getEntity();
$user = $this->container->get('security.context')->getToken()->getUser();
$entity->setUser($user);
}
}
这样做对吗?还是存在另一个?我读到注入整个容器是个坏主意,因为我只需要安全上下文,那么解决方案是什么?()
尝试转换服务中的UserCallable
我正试图在服务中转换UserCallable
,方法是按照说明进行转换,并查看和了解他们是如何进行转换的,但由于出现以下错误,我无法使其正常工作:
ContextErrorException:可捕获致命错误:参数1传递给
PL\OrderBundle\Listener\OrderHasCommentListener::\uu构造()必须为
可调用,字符串给定
这就是我在app/config/config.yml中的定义:
services:
orderhascomment.listener:
class: PL\OrderBundle\Listener\OrderHasCommentListener
arguments:
- user_callable
tags:
- { name: doctrine.event_listener, event: prePersist, method: onPrePersist }
user_callable:
class: PL\OrderBundle\Util\UserCallable
arguments:
- "@service_container"
public: false
这就是我如何在OrderHasCommentListener.php
文件中传递到\u construct()
函数的方法:
/**
* @param UserCallableInterface $user_callable
* */
public function __construct(callable $user_callable = null) {
$this->userCallable = $user_callable;
}
怎么了?将整个容器直接注入列表器可能是一个有效的解决方案。。。但我们可以做得更好:)
插入一个UserCallable
,返回当前用户
通过这种方式,您可以更清楚地表达依赖性的真正目的,而无需在侦听器和容器(-interface)之间引入硬依赖性。例如
通过创建一个接口并将其用于侦听器中的类型暗示,可以进一步改进这个特定示例。如果您计划重新使用侦听器,那么可以更容易地进行交换
接口:
namespace Acme\Common;
interface UserCallableInterface
{
/**
* @return \Symfony\Component\Security\Core\User\UserInterface
*/
public function getCurrentUser();
}
namespace Acme\Util;
use Acme\Common\UserCallableInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UserCallable implements UserCallableInterface
{
/** @var ContainerInterface **/
protected $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* @{inheritdoc}
*/
public function getCurrentUser()
{
return $this->container->get('security.context')->getToken()->getUser() ?: false;
}
use Acme\Common\UserCallableInterface;
use Acme\Common\TrackableInterface;
use Doctrine\Common\EventArgs;
class Listener
{
/** @var UserCallableInterface **/
protected $userCallable;
/**
* @param UserCallableInterface $user_callable
**/
public function __construct(UserCallableInterface $user_callable)
{
$this->userCallable = $user_callable;
}
/**
* @param EventArgs $args
**/
public function onPrePersist(EventArgs $args)
{
$entity = $args->getEntity();
if ( !($entity instanceof TrackableInterface) ) {
return;
}
if ( !($user = $this->userCallable->getCurrentUser())) {
return;
}
$entity->setUser($user);
}
}
用户可调用:
namespace Acme\Common;
interface UserCallableInterface
{
/**
* @return \Symfony\Component\Security\Core\User\UserInterface
*/
public function getCurrentUser();
}
namespace Acme\Util;
use Acme\Common\UserCallableInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UserCallable implements UserCallableInterface
{
/** @var ContainerInterface **/
protected $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* @{inheritdoc}
*/
public function getCurrentUser()
{
return $this->container->get('security.context')->getToken()->getUser() ?: false;
}
use Acme\Common\UserCallableInterface;
use Acme\Common\TrackableInterface;
use Doctrine\Common\EventArgs;
class Listener
{
/** @var UserCallableInterface **/
protected $userCallable;
/**
* @param UserCallableInterface $user_callable
**/
public function __construct(UserCallableInterface $user_callable)
{
$this->userCallable = $user_callable;
}
/**
* @param EventArgs $args
**/
public function onPrePersist(EventArgs $args)
{
$entity = $args->getEntity();
if ( !($entity instanceof TrackableInterface) ) {
return;
}
if ( !($user = $this->userCallable->getCurrentUser())) {
return;
}
$entity->setUser($user);
}
}
听众:
namespace Acme\Common;
interface UserCallableInterface
{
/**
* @return \Symfony\Component\Security\Core\User\UserInterface
*/
public function getCurrentUser();
}
namespace Acme\Util;
use Acme\Common\UserCallableInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UserCallable implements UserCallableInterface
{
/** @var ContainerInterface **/
protected $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* @{inheritdoc}
*/
public function getCurrentUser()
{
return $this->container->get('security.context')->getToken()->getUser() ?: false;
}
use Acme\Common\UserCallableInterface;
use Acme\Common\TrackableInterface;
use Doctrine\Common\EventArgs;
class Listener
{
/** @var UserCallableInterface **/
protected $userCallable;
/**
* @param UserCallableInterface $user_callable
**/
public function __construct(UserCallableInterface $user_callable)
{
$this->userCallable = $user_callable;
}
/**
* @param EventArgs $args
**/
public function onPrePersist(EventArgs $args)
{
$entity = $args->getEntity();
if ( !($entity instanceof TrackableInterface) ) {
return;
}
if ( !($user = $this->userCallable->getCurrentUser())) {
return;
}
$entity->setUser($user);
}
}
嗯,我以前从来没有这样做过,所以我完全不明白这一点也许一段使用Listener或Entity的代码会对我有更好的帮助(我是新手),所以希望你能帮助我,你还不清楚什么?我很乐意改进我的答案。我尝试了你的代码,得到了这个错误ContextErrorException:可捕获的致命错误:传递给PL\OrderBundle\Listener\OrderHasCommentListener的参数1::\uu construct()必须是PL\OrderBundle\UserCallableInterface的实例,给定的AppDevDebBugProjectContainer实例
OK-您需要将usercallable转换为服务,并注入此服务而不是容器。这是这种方法的关键所在。我将添加一些说明并重新编写答案-挂起:)顺便说一句,使用$this->container->get('security.authorization\u checker')
(2.6中新增)请参见此处的“security.token\u storage”解决方案: