37

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

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

我正在使用 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

我错过了什么吗?

4

7 回答 7

59

我认为自 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
    }
}

服务.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments:
        - "@security.token_storage"
于 2015-03-12T18:00:46.747 回答
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
    }

现在在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>

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

{{ date | user_date('d/m/Y') }}
于 2012-04-03T09:49:03.903 回答
30

服务.yml

my_service:
    class: ...
    arguments:
        - "@=service('security.token_storage').getToken().getUser()"

服务.php

protected $currentUser;

public function __construct($user)
{
    $this->currentUser = $user;
}

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

于 2016-05-25T15:29:25.240 回答
4

用户不适合成为服务。

  • 首先它是一个模型而不是一个服务
  • 其次是服务security.context,您可以从中获取用户。

在树枝模板中,您可以使用app.user。请参阅 symfony 文档global-template-variables。如果您想根据用户权限显示某些内容,您可以执行 {{ is_granted('ROLE_USER') }}。

于 2013-05-31T08:48:42.573 回答
2

来自 Symfony 2.6。

你需要使用@security.token_storage

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

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


/**
 * @param $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
}

}

和服务.yml

twig.date_extension:
    class: Acme\Twig\SpecialDateExtension
    tags:
        - { name: twig.extension }
    arguments: ["@security.token_storage"]

参考: http ://symfony.com/blog/new-in-symfony-2-6-security-component-improvements

于 2016-08-18T10:52:11.207 回答
1

我建议绑定一个不同的事件,如果您使用 kernel.controller 事件,您将有一个令牌并且没有问题。令牌不可用,kernel.request因为Symfony 2.3

我在名为Symfony 2.6+ User TimezonesSymfony 2.3+的博客上写了一篇关于如何2.6+在 Twig中实现用户时区的指南。

这比使用 Twig 扩展要好得多,因为您可以在 Twig 中使用标准日期格式化功能,并提供单独的后端 UTC 日期、默认 Twig 日期时区和用户定义的 Twig 日期时区。

这是最重要的摘录:

src/AppBundle/EventListener/TwigSubscriber.php

<?php

namespace AppBundle\EventListener;

use AppBundle\Entity\User;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class TwigSubscriber implements EventSubscriberInterface
{
    protected $twig;
    protected $tokenStorage;

    function __construct(\Twig_Environment $twig, TokenStorageInterface $tokenStorage)
    {
        $this->twig = $twig;
        $this->tokenStorage = $tokenStorage;
    }

    public static function getSubscribedEvents()
    {
        return [
            'kernel.controller' => 'onKernelController'
        ];
    }

    public function onKernelController(FilterControllerEvent $event)
    {
        $token = $this->tokenStorage->getToken();

        if ($token !== null) {
            $user = $token->getUser();

            if ($user instanceof User) {
                $timezone = $user->getTimezone();
                if ($timezone !== null) {
                    $this->twig->getExtension('core')->setTimezone($timezone);
                }
            }
        }
    }
}

现在您可以正常使用 twig,它会使用您的用户偏好(如果可用)。

于 2015-06-10T15:25:18.170 回答
-9

您可以尝试注入@service_container并执行$this->container->get('security.context')->getToken()->getUser();.

于 2012-04-03T09:45:59.347 回答