简体   繁体   English

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

[英]How to dynamic handle roles|permissions in Symfony2 at database level: CRUD operations over them

I am working in a Symfony 2.8 project and I have a doubt regarding users/groups/roles|permissions. 我在Symfony 2.8项目中工作,对用户/组/角色有疑问。 There are a few ways to handle users and groups as for example SonataUser on top of SonataAdmin and lately EasyAdmin but all of them lacks ROLE|permissions management and this is exactly my doubt: what's the proper way to handle them? 有几个方式来处理用户和组,例如SonataUser之上SonataAdmin ,最近EasyAdmin但他们都缺少角色|权限管理,这正是我的疑问:什么是处理他们的正确方法? Yes, I know I need to write them at security.yml but I don't know if I can store then in DB (somewhere) and then read from there. 是的,我知道我需要在security.yml上编写它们,但是我不知道是否可以将其存储在DB(某处)中,然后从那里读取。 I have research about this and found ACL, Voters and so on but instead of clear my mind the research is confusing me a lot so I need some push from people here. 我对此进行了研究,找到了ACL,选民等,但并没有使我头脑清醒,但这项研究使我感到非常困惑,因此我需要这里的人提供一些帮助。 Then: 然后:

  • How would you handle this? 您将如何处理?
  • Any example at code level? 在代码级别有什么例子吗? (I prefer to see something other than words to get the whole point) (我更喜欢看文字以外的东西来理解整个观点)
  • Are ROLES sames as permissions? ROLES是否与权限相同?

Update: improve question 更新:改善问题

What I want to have is a ManyToMany relationship between users and roles and possibly groups and roles . 我要拥有的是usersroles之间以及groupsroles之间的ManyToMany关系。 I think that as SonataUserBundle handle this is by creating a column roles in user table and assign a lot of roles to each user, even create new ones if I'm not mistaken but what about if I want to create as much roles as I can without assign them to a user and later add many roles to a user even to a group? 我认为,通过SonataUserBundle处理此问题的方法是,在user表中创建列roles ,并为每个用户分配很多角色,如果我没记错的话甚至创建新角色,但是如果我想创建尽可能多的角色呢?而不将它们分配给用户,以后再向用户甚至向组添加许多角色?

How would you do that? 你会怎么做?

You can add new roles in the FOSUserBundle on the go. 您可以FOSUserBundleFOSUserBundle添加新角色。 There is no need for you to initially add it in the security.yml file. 您无需首先将其添加到security.yml文件中。

To do this you can do something like this: 为此,您可以执行以下操作:

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

or in your controller you can get current or any user 或在您的控制器中,您可以获取当前用户或任何用户

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

This answers your first and second part. 这回答了您的第一部分和第二部分。

For the third part, Roles can be used as permissions. 对于第三部分, 可以将角色用作权限。 I have implemented a structure previously where I was restricting access to pages based on the user role also restricting what data they can change based on their role. 以前,我已经实现了一个结构,在该结构中,我根据用户角色来限制对页面的访问,还根据用户角色来限制可以更改哪些数据。

UPDATE I implemented an Event Listener for this which would listen to all the kernel requests which is called onKernelRequest . 更新我为此实现了一个事件侦听器 ,该侦听器将侦听所有称为onKernelRequest的内核请求。 I have partially done the access management on the SQL side since I have my roles stored in SQL side as well but one can do the same on the Server side. 由于我的角色也存储在SQL端,所以我在SQL端做了部分访问管理,但是在Server端也可以做同样的事情。 My Event Listener looked like this: (This is a trimmed down version of what I have) 我的事件监听器看起来像这样:(这是我所拥有的精简版本)

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

My services.yml looks like this 我的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 }

UPDATE To answer your update part of the question, what you can do is have another roles entity and you could populate the roles you want in advance and then have a one to many relationship with the original User table. UPDATE要回答问题的更新部分,您可以做的是拥有另一个roles实体,您可以预先填充所需的角色,然后与原始User表建立一对多关系。 You can then have something like prePersist or preUpdate Doctrine Lifecycle Events to check when adding a new if the role already exists in your roles entity. 然后,如果角色实体中已经存在该角色,则可以使用诸如prePersist or preUpdate Doctrine Lifecycle Events来检查何时添加新角色。 That should precisely solve your problem. 那应该可以解决您的问题。 All this will involve a little tweaking though. 所有这些都将涉及一些调整。 There is no straight way to do this. 没有直接的方法可以做到这一点。

It depends how you want to implement this. 这取决于您要如何实现。

One approach: 一种方法:

Implement the UserProviderInterface to loadByUsername (this is where you load the roles and permissions) an implementation of a UserInterface (your User ). UserProviderInterface实现为loadByUsername (在此加载角色和权限)到UserInterface (您的User )的实现。

Then Implement the VoterInterface . 然后实现VoterInterface Register this as a service tagged with security.voter and specify it as a provider in security.yml. 将其注册为带有security.voter标记的服务,并在security.yml中将其指定为提供程序。 Override the vote function to assess the User you loaded for permissions (and maybe roles too) from TokenInterface which is the first argument of that function. 覆盖vote功能,以评估从TokenInterface加载的User的权限(可能还有角色), TokenInterface是该功能的第一个参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM