Symfony2:在服务中注入当前用户

n0x*_*xie 38 php dependency-injection symfony fosuserbundle

我试图将当前登录的用户注入服务.我的目标是扩展一些树枝功能,根据用户偏好输出它.在这个例子中,我想使用用户特定的时区输出任何日期函数.

似乎没有任何方法可以将当前用户注入服务,这对我来说似乎很奇怪.注入安全上下文时,即使用户已登录,它也没有令牌

我正在使用FOS用户包.

services:
    ...
    twigdate.listener.request:
        class: App\AppBundle\Services\TwigDateRequestListener
        arguments: [@twig, @security.context]
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }


<?php

namespace App\AppBundle\Services;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class TwigDateRequestListener
{
    protected $twig;

    function __construct(\Twig_Environment $twig, SecurityContext $context) {

        $this->twig = $twig;
        //$this->user = $context->get...;

        var_dump($context); die;
    }

    public function onKernelRequest(GetResponseEvent $event) {
       // $this->twig->getExtension('core')->setDateFormat($user->getProfile()->getFormat());
       // $this->twig->getExtension('core')->setTimeZone($user->getProfile()->getTimezone());
    }
}

output:

object(Symfony\Component\Security\Core\SecurityContext)[325]
  private 'token' => null
  private 'accessDecisionManager' => 
    object(Symfony\Component\Security\Core\Authorization\AccessDecisionManager)[150]
      private 'voters' => 
        array
          0 => 
            object(Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter)[151]
              ...
          1 => 
            object(Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter)[153]
              ...
          2 => 
            object(Symfony\Component\Security\Acl\Voter\AclVoter)[155]
              ...
      private 'strategy' => string 'decideAffirmative' (length=17)
      private 'allowIfAllAbstainDecisions' => boolean false
      private 'allowIfEqualGrantedDeniedDecisions' => boolean true
  private 'authenticationManager' => 
    object(Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager)[324]
      private 'providers' => 
        array
          0 => 
            object(Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider)[323]
              ...
          1 => 
            object(Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider)[149]
              ...
      private 'eraseCredentials' => boolean true
  private 'alwaysAuthenticate' => boolean false
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

Mic*_*uve 60

我认为自从新的安全组件改进以来2.6.x +以来这个问题值得更新.

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

class UserDateExtension extends \Twig_Extension
{
    /**
     * @var TokenStorage
     */
    protected $tokenStorage;


    /**
     * @param \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage    $tokenStorage
     */
    public function __construct(TokenStorage $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function getUser()
    {
        return $this->tokenStorage->getToken()->getUser();
    }

    public function getFilters()
    {
        return array(
            'user_date' => new \Twig_Filter_Method($this, "formatUserDate"),
        );
    }

    public function formatUserDate($date, $format)
    {
        $user = $this->getUser();
        // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

Services.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments:
        - "@security.token_storage"
Run Code Online (Sandbox Code Playgroud)


小智 42

我会使用一个枝条扩展:

class UserDateExtension extends \Twig_Extension
{
    private $context;

    public function __construct(SecurityContext $context)
    {
        $this->context = $context;
    }

    public function getUser()
    {
        return $this->context->getToken()->getUser();
    }

    public function getFilters()
    {
        return array(
            'user_date' => new \Twig_Filter_Method($this, "formatUserDate"),
        );
    }

    public function formatUserDate($date, $format)
    {
        $user = $this->getUser();
        // do stuff
    }
Run Code Online (Sandbox Code Playgroud)

现在进来 services.xml

    <service id="user_date_twig_extension" class="%user_date_twig_extension.class%">
        <tag name="twig.extension" />
        <argument type="service" id="security.context" />
    </service>
Run Code Online (Sandbox Code Playgroud)

然后在树枝上你可以这样做:

{{ date | user_date('d/m/Y') }}
Run Code Online (Sandbox Code Playgroud)

  • 自2.6以来,不推荐使用SecurityContext(security.context).请改用security.token_storage (8认同)
  • 那你正在听'kernel.request`事件.在调度所有`kernel.request`侦听器之后,通过身份验证设置上下文令牌或从会话中读取令牌.如果您已经听过`kernel.response`事件,那么您将获得所需的令牌.也很遗憾误读了你的问题.对我来说这是糟糕的一天:). (2认同)

小智 30

services.yml

my_service:
    class: ...
    arguments:
        - "@=service('security.token_storage').getToken().getUser()"
Run Code Online (Sandbox Code Playgroud)

Service.php

protected $currentUser;

public function __construct($user)
{
    $this->currentUser = $user;
}
Run Code Online (Sandbox Code Playgroud)

http://symfony.com/doc/current/book/service_container.html#using-the-expression-language

  • 它是否在安全防火墙之外工作?我的意思是,它返回"null"还是抛出异常,因为getToken()返回null并且 - > getUser()不能应用于null对象? (11认同)
  • 我相信当没有用户时,这会抛出错误. (3认同)
  • 这是2016年symfony 2.6及以上的最佳答案 (2认同)