如何动态地向用户添加角色?

时间:2014-05-27 20:13:20

标签: symfony symfony-2.4

当用户登录时,无论是第一次登录还是通过现有的cookie登录,我都希望根据我运行的某些查询的结果为他们分配一个或多个其他用户角色。

我认为我需要创建一个事件监听器来注入安全组件和实体管理器,这样我就可以运行查询并向当前用户添加角色。

我不太确定事件是否可行,因为事件需要在授权完成之前在防火墙上下文中触发,但在身份验证之后。

我确实看到了this existing question,但我无法让它工作(在运行事件后,角色实际上无法识别)。

是否可以使用事件监听器执行此操作?

我认为我的替代方案是在User实体上使用postload生命周期回调并在那里运行一些查询,但这似乎不正确。

1 个答案:

答案 0 :(得分:3)

您可以在内核上创建一个事件侦听器。它将在每次加载页面时运行。

它会检查他们是否是登录用户,然后你可以做一些自定义逻辑来查看你是否需要更新他们的角色,如果你这样做,那么更新它会用新设置登录,然后他们会“#”;将继续使用他们的新角色加入系统。

我还没有测试过这段代码,所以可能会有一些错误。

services.yml

bundle.eventlistener.roles:
    class: Sample\MyBundle\EventListener\Roles
    arguments: [@service_container, @security.context]
    tags:
        - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

监听\ Roles.php

namespace Sample\MyBundle\EventListener;

use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

use Sample\MyBundle\Entity\Users; //Your USER entity

class Roles {
    private $container;
    private $context;

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

    public function onKernelController(FilterControllerEvent $event) {
        if($this->context->getToken()->getUser() instanceof Users) {

            //Custom logic to see if you need to update the role or not.

            $user = $this->context->getToken()->getUser();

            //Update your roles
            $user->setRole('ROLE_WHATEVER');

            $em = $this->container->get('doctrine')->getManager();
            $em->persist($user);
            $em->flush();

            //Create new user token
            //main == firewall setting
            $token = new UsernamePasswordToken($user, $user->getPassword(), 'main', $user->getRoles());

            $this->context->setToken($token);
        }
    }
}