Symfony2:注入@ security.context以获取当前用户.如何避免"ServiceCircularReferenceException"?注入整个容器?

Rey*_*rPM 4 security dependency-injection symfony doctrine-orm

来自这个帖子和修复后的东西我在另一个问题/安全问题/问题.

正如你在其他帖子中看到的那样,我正在尝试在监听器中注入安全上下文,但是如果我保持代码完整而没有触摸我得到了这个错误:

ServiceCircularReferenceException:检测到服务"doctrine.orm.default_entity_manager"的循环引用

因此,阅读和研究我找到了一个解决方案,但我不清楚它是否是正确的,或者它对我的应用程序是否安全.所以这就是我做的:

而不是注入[@security.context]我这样做:

services:
    orderhascomment.listener:
        class: PL\OrderBundle\Listener\OrderHasCommentListener
        arguments: [@service_container]
        tags:
            - { name: doctrine.event_listener, event: prePersist, method: onPrePersist }
Run Code Online (Sandbox Code Playgroud)

我的听众OrderHasCommentListener.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);
    }

}
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?还是存在另一个?我认为注入整个容器是一个坏主意,因为我只需要安全上下文,那么解决方案是什么?(https://insight.sensiolabs.com/what-we-analyse)

试图在服务中转换UserCallable

我正在尝试UserCallable按照这里的说明转换服务,看看DoctrineBehaviors orm-services.yml文件,看看他们是如何在BlameableListener上做的,但是因为我收到这个错误所以无法让它工作:

ContextErrorException:Catchable Fatal Error:传递给PL\OrderBundle\Listener\OrderHasCommentListener :: __ construct()的参数1必须是可调用的,给定字符串

这就是我的定义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
Run Code Online (Sandbox Code Playgroud)

这就是我__construct()OrderHasCommentListener.php文件中传递函数的方式:

/**
 * @param UserCallableInterface $user_callable 
 * */
public function __construct(callable $user_callable = null) {
    $this->userCallable = $user_callable;
}
Run Code Online (Sandbox Code Playgroud)

怎么了?

Nic*_*ich 9

将整个容器直接注入列表器可能是一个有效的解决方案...但我们可以做得更好:)

注入一个UserCallable返回当前用户的.

这样,您可以更清楚地表达依赖关系的真正目的,而不会在侦听器和容器(-interface)之间引入硬依赖关系.一个例子是......

Knp\DoctrineBehaviors\ORM\Blameable\UserCallable

通过创建一个接口并将其用于侦听器中的类型提示,可以进一步改进此特定示例.如果您计划重新使用侦听器,则可以更轻松地进行交换.

接口:

namespace Acme\Common;

interface UserCallableInterface
{
    /**
     * @return \Symfony\Component\Security\Core\User\UserInterface
     */
    public function getCurrentUser();
}
Run Code Online (Sandbox Code Playgroud)
namespace Acme\Common;

use Symfony\Component\Security\Core\User\UserInterface;

interface TrackableInterface
{
    /**
     * @param UserInterface $user
     */
    public function setUser(UserInterface $user);
}
Run Code Online (Sandbox Code Playgroud)

UserCallable:

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;
   }
Run Code Online (Sandbox Code Playgroud)

听众:

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);
    }      
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

7736 次

最近记录:

11 年,5 月 前