如何在使用symfony2(和fosUserBundle)登录时动态添加用户角色?

时间:2012-09-05 14:19:29

标签: php symfony fosuserbundle

在我的应用中,用户可以随着时间的推移在免费用户和高级用户之间切换,当他们的订阅到期时,他们不再拥有高级优先权。

我认为我可以削减一个角落,而不是将高级用户角色存储在数据库中,只存储他们已支付的日期,因此无需添加och作业,从我的用户中删除角色溢价。< / p>

我想到的解决方案是在用户实体上执行此操作:

public function __construct()
{
    if ( $this->hasPlus() )
    {       
        $this->addRole('ROLE_PLUSUSER');
    }
}

其中hasPlus是一个将当前日期与付款日期进行比较的函数,如果用户仍然付款,则返回true。

现在,这不起作用,所以我想也许有人可以为我揭示这一点 - 我知道登录时添加了角色,如果我在登录后添加角色,我需要注销并重新登录它生效,但在这里我试图在构建我的用户对象时添加角色,但它仍然无效...

根据下面的优秀答案添加了eventListener,仍无法将该角色添加到用户:

<?php

namespace Hemekonomi\UserBundle\EventListener;

use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Session;


class SecurityListener
{
    protected $security;
    protected $session;

/**
* Constructs a new instance of SecurityListener.
*
* @param SecurityContext $security The security context
* @param Session $session The session
*/
    public function __construct(SecurityContext $security, Session $session)
    {
        //You can bring whatever you need here, but for a start this should be useful to you
        $this->security = $security;
        $this->session = $session;
    }

/**
* Invoked after a successful login.
*
* @param InteractiveLoginEvent $event The event
*/
    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
    {
         //Your logic needs to go here
         //You can addRole 
         //Even persist if you want but bring the right tools to your constructor
         $security = $this->security; 

         if ($security->getToken()->getUser()->hasPlus()) {       
            $security->getToken()->getUser()->addRole('ROLE_PLUSUSER');    
         }

    }
}

1 个答案:

答案 0 :(得分:2)

您的逻辑不适用于user实体......

如果你想要实现的目标是登录,请使用Event Listeners,这就是它们如此有用的原因: - )

您需要创建的是一个对事件InteractiveLoginEvent作出反应的侦听器,如下所示:

1 /创建一个监听器

<?php

namespace Acme\YourBundle\EventListener;

use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Session\Session;


class SecurityListener
{
    protected $security;
    protected $session;

/**
* Constructs a new instance of SecurityListener.
*
* @param SecurityContext $security The security context
* @param Session $session The session
*/
    public function __construct(SecurityContext $security, Session $session)
    {
        //You can bring whatever you need here, but for a start this should be useful to you
        $this->security = $security;
        $this->session = $session;
    }

/**
* Invoked after a successful login.
*
* @param InteractiveLoginEvent $event The event
*/
    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
    {
         //Your logic needs to go here
         //You can addRole 
         //Even persist if you want but bring the right tools to your constructor
    }
}

请记住,Symfony中已经默认创建了 InteractiveLoginEvent (正如您在use语句中看到的那样),所以现在几乎没有什么可做的:

2 /将此侦听器声明为服务:

services:
    acme_your_bundle.listener.login:
        class: Acme\YourBundle\EventListener\SecurityListener
        arguments: [@security.context, @session]
        tags:
            - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }

3 /如果需要,请检查文档

The Event Dispatcher Component

How to create an Event Listener

Login Redirection by Dustin Dobervich:这篇文章将为您提供一个关于听众如何工作以及如何在登录时简单实现它们的好例子。

相关问题