3

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

我想我可以偷工减料,不在数据库中存储高级用户角色,只存储他们支付的日期,从而无需 cron 作业添加 och 从我的用户中删除角色高级。

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

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');    
         }

    }
}
4

1 回答 1

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/ 如果需要,请查看文档

事件调度程序组件

如何创建事件监听器

Dustin Dobervich 的登录重定向:这篇文章将为您提供一个很好的示例,说明监听器如何工作以及如何在登录时简单地实现它们。

于 2012-09-07T06:25:46.833 回答