如何为用户动态添加角色?

Bri*_*ian 3 symfony symfony-2.4

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

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

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

我确实看到了这个现有的问题,但我无法让它工作(在事件运行后实际上无法识别角色)。

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

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

ske*_*hat 7

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

它将检查他们是否是登录用户,然后您可以执行一些自定义逻辑以查看是否需要更新他们的角色,如果您需要更新它,请使用新设置登录他们,然后他们将继续在系统中与他们的新角色。

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

服务.yml

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

侦听器\角色.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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)