如何在数据库级别动态处理Symfony2中的角色|权限:对它们的CRUD操作

时间:2015-12-09 17:00:32

标签: php symfony security acl

我在Symfony 2.8项目中工作,我对用户/组/角色|权限有疑问。有几种方法可以处理用户和组,例如SonataUserSonataAdmin之上的EasyAdmin,但所有这些方法都缺乏ROLE |权限管理,这正是我的疑问:什么& #39;是处理它们的正确方法吗?是的,我知道我需要在security.yml写一下,但我不知道我是否可以在DB(某处)存储然后从那里读取。我对此进行了研究,发现了ACL,Voters等等,但我没有清楚自己的想法,研究让我很困惑,所以我需要一些来自这里的人。然后:

  • 你会怎么处理这个?
  • 代码级别的任何示例? (我更喜欢看到除了文字以外的其他内容以获得重点)
  • ROLES与权限相同吗?

更新:改进问题

我想要的是ManyToManyusers以及可能rolesgroups之间的roles关系。我认为,当SonataUserBundle处理时,可以在roles表格中创建一个列user,并为每个用户分配很多角色,如果我没有弄错的话,甚至可以创建新的角色但是,如果我想创建尽可能多的角色而不将它们分配给用户,然后将更多角色添加到用户甚至添加到组中呢?

你会怎么做?

2 个答案:

答案 0 :(得分:2)

您可以随时随地在FOSUserBundle添加新角色。您无需先将其添加到security.yml文件中。

要做到这一点,你可以这样做:

$user = new User();
$user->addRole('ROLE_NEWUSER'); //Role Name should begin with 'ROLE_'

或在您的控制器中,您可以获得当前用户或任何用户

$this->getUser();
$user->addRole('ROLE_NEWUSER'); //Role Name should begin with 'ROLE_'

这回答了你的第一和第二部分。

对于第三部分,Roles 可以用作权限。我之前已经实现了一个结构,我根据用户角色限制对页面的访问,同时根据角色限制他们可以更改的数据。

UPDATE 我为此实现了一个Event Listener,它将侦听所有称为onKernelRequest的内核请求。我已经部分完成了SQL端的访问管理,因为我的角色也存储在SQL端,但是在服务器端可以做同样的事情。我的事件监听器看起来像这样:(这是我所拥有的精简版)

class TokenListener
{
    protected $em;
    protected $token_storage;
    protected $templating;
    protected $router;
    protected $resolver;
    public function __construct($em,TokenStorageInterface $token_storage, TwigEngine $templating, Router $router, ControllerResolver $resolver)
    {
        $this->em = $em;
        $this->token_storage = $token_storage;
        $this->templating = $templating;
        $this->router = $router;
        $this->resolver = $resolver;
    }


    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $route  = $request->attributes->get('_route');
        $routeArr = array('fos_js_routing_js', 'fos_user_security_login', '_wdt'); //These are excluded routes. These are always allowed. Required for login page
        if(!is_int(array_search($route, $routeArr)) && false)
        {
            $userRoles = $this->token_storage->getToken()->getUser()->getRoles();
            if(!in_array('ROLE_NEWUSER', $userRoles))
            {
                $event->setResponse(new RedirectResponse($this->router->generate('user_management_unauthorized_user', array())));
            }
        }
    }
}

我的services.yml看起来像这样

services:
    app.tokens.action_listener:
        class: EventListenerBundle\EventListener\TokenListener
        arguments:
            entityManager: "@doctrine.orm.entity_manager"
            token_storage: "@security.token_storage"
            templating: "@templating"
            router: "@router"
            resolver: "@controller_resolver"
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

更新要回答问题的更新部分,您可以做的是拥有另一个roles实体,您可以提前填充所需的角色,然后进行一对多与原始User表的关系。然后,如果角色实体中已存在角色,则可以在添加新内容时检查prePersist or preUpdate Doctrine Lifecycle Events之类的内容。那应该可以解决你的问题。所有这些都将涉及一些调整。没有直接的方法可以做到这一点。

答案 1 :(得分:0)

这取决于你想要如何实现它。

一种方法:

UserProviderInterface实施为loadByUsername(这是您加载角色和权限的位置)UserInterface(您的User)的实现。

然后实施VoterInterface。将此注册为标记为security.voter的服务,并将其指定为security.yml中的提供程序。覆盖vote函数,以评估User您从TokenInterface获取的权限(也可能是角色),这是该函数的第一个参数。