如何使用symfony2(和fosUserBundle)登录时动态添加用户角色? [英] how to add user roles dynamically upon login with symfony2 (and fosUserBundle)?

查看:72
本文介绍了如何使用symfony2(和fosUserBundle)登录时动态添加用户角色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我想我可以开个弯,不将高级用户角色存储在数据库中,而只存储他们的付款日期,从而消除了执行Cron作业的需要,而且还可以从用户中删除高级角色. /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');    
         }

    }
}

解决方案

您的逻辑不适用于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
    }
}

请记住, InteractiveLoginEvent 已默认在Symfony中创建(如您在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的登录重定向:这篇文章将为您提供了一个很好的示例,说明了侦听器的工作方式以及如何在登录时简单实现它们.

In my app users can switch between free user and premium user over time, when their subscription expires, they no longer have premium previleges.

I thought I could cut a corner and not store the premium user role in the database, only store the date to which they have paid, thus eliminating the need for a cron job adding och removing the role premium from my users.

The solution I had in mind was to do this on the user entity:

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

Where hasPlus is a function that compares the current date with the paid-to date and returns true if user has still paid.

Now, this doesn't work, so I was thinking maybe someone could shed light on this for me - I know roles are added upon login, and if I add a role after login I need to log out and back in for it to take effect, but here I am trying to add the role upon constructing my user object, still it doesn't work...

Added the eventListener as per the excellent answer below, still can't add the role to the user:

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

    }
}

解决方案

Your logic will not work on the user entity...

If what you want to achieve is upon login, use Event Listeners, that's why they are so useful :-)

What you will need to create is a Listener that reacts to the event InteractiveLoginEvent, something like this:

1/ Create a listener

<?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
    }
}

Keep in mind that InteractiveLoginEvent is already created by default in Symfony (as you can see in the use statement) so there is very little to do now:

2/ Declare this listener as a service:

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/ Check the doc if you need to

The Event Dispatcher Component

How to create an Event Listener

Login Redirection by Dustin Dobervich: This post will give you a good example on how listeners work and how you can simply implement them upon login.

这篇关于如何使用symfony2(和fosUserBundle)登录时动态添加用户角色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆