如何动态手柄角色|在Symfony2的权限:限制使用动态角色功能 [英] How to dynamic handle roles|permissions in Symfony2: restrict functions with dynamic roles

查看:124
本文介绍了如何动态手柄角色|在Symfony2的权限:限制使用动态角色功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该职位的目标是成为一种<第二部分href=\"http://stackoverflow.com/questions/34184630/how-to-dynamic-handle-rolespermissions-in-symfony2-at-database-level-crud-oper/\">this后,所以你可能要读得懂这个问题。有了这样的信息,并从previous后的答案,也已经发现的有用的 UserBundle ,帮助我作为一个例子来说明尽可能关系多对多 角色之间用户我可能会问:

This post aims to be a kind of second part of this post so you may have to read it to understand this question. Having that info and the answer from previous post and also having found this useful UserBundle which help me as an example to illustrate possible relationship as Many To Many between roles and users I may ask:


  • 我有动态的角色,现在我是如何使用这些新的角色

  • I have dynamic roles and now how I use those new ROLES?

我的意思,比如我要限制存在的功能,它已被动态创建的角色 ROLE_NEWROLE ,因此不存在对基础code (原始资料),那我怎么限制一个存在的功能,这个新角色?就拿文档<一个href=\"http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/security.html#usage\"相对=nofollow>这里为例:

What I mean, for example I want to limit a existent function to role ROLE_NEWROLE which has been created dynamically and therefore doesn't exists on the base code (original sources) then how do I restrict a existent function to that new role? Take the docs here as an example:

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

class PostController extends Controller
{
    /**
     * @Security("has_role('ROLE_ADMIN')")
     */
    public function indexAction()
    {
        // ...
    }
}

在code以上presume的 ROLE_ADMIN 已经某处不知何故,但如果我想增加新的什么声明 ROLE_NEWROLE 通过安全组件的功能?我需要摸我的code所有的时间?这是不好笑,所以我想知道你对这个话题的看法。

The code above presume that ROLE_ADMIN is already declared somewhere and somehow but what if I want to add the new ROLE_NEWROLE to that function through security component? Do I need to touch my code all the time? That isn't funny at all so I want to know your opinions about this topic.

推荐答案

正如我们之前谈到这个,你需要实施的EventListener 将倾听你的 onKernelRequest

As we talked about this before, you need to implement EventListener which will listen to your onKernelRequest.

在简单的英语,这意味着您的控制器操作的所有将执行 onKernelRequest 先给予访问原始控制器之前。所以,这样你就不必写

In plain English, this means that all of your Controller Actions will execute onKernelRequest first before giving access to the original controller. So this way you won't have to write

/**
* @Security("has_role('ROLE_ADMIN')")
*/

在每个控制器动作。

现在,其高达你想要的在这个方法中做什么。我的方法是使该相关联的角色路线表。该表将是比较大的,因为你必须包括所有的角色你想给访问所有路线

Now, its upto you what you want to do in this method. My approach was to make a table which associates a ROLE with a ROUTE. This table will be comparatively big because you have to include all ROLES you want to give access to all ROUTES.

表结构可以是这样的:

ACCESSID      ROLENAME                ROUTENAME
    1       ROLE_NEWUSER       contacts_lookup_homepage
    2       ROLE_SUPER_USER    contacts_lookup_homepage

根据此表仅 ROLE_NEWUSER ROLE_SUPER_USER 有资格进入的路线 contacts_lookup_homepage

这种方式现在只有这些角色被允许访问 contacts_lookup_homepage 路线。现在,在 onKernelRequest 所有你要做的就是查询这个表,检查是否存在与与路由的角色匹配。你必须在该方法中访问两者。这些路由是一样的,你在每一个路线的的routing.yml 文件中定义之一。如果你不知道,它看起来是这样的:

This way now only those roles are allowed to access contacts_lookup_homepage route. Now on the onKernelRequest all you will do is query this table and check if there is a match with that role with that route. You have access to both in this method. These routes are the same as the one you define in your routing.yml file of every route. If you're not sure, it looks something like this:

contacts_lookup_homepage:
    path:     /Contacts/Lookup
    defaults: { _controller: ContactsLookupBundle:Default:index }

现在终于在你的 onKernelRequest 你可以做这样的事情:

Now finally in your onKernelRequest you can do something like this:

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
    $roleArr = $this->token_storage->getToken()->getUser()->getRoles();

    if(!is_int(array_search($route, $routeArr))) //This is for excluding routes that you don't want to check for.
    {
        //Check for a matching role and route
        $qb = $this->em->getRepository('AppBundle:UserAccess')->createQueryBuilder('o');
        $qb
            ->select('o')
            ->where('o.ROLENAME IN (:roleArr)')
            ->setParameter('roleArr', $roleArr)
            ->andWhere('o.ROUTENAME = :route')
            ->setParameter('route', $route)
        ;
        $result = $qb->getQuery()->getArrayResult();
        if(empty($result))
        {
            //A matching role and route was not found so we do not give access to the user here and redirect to another page.
            $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 }

这将保证未经授权的用户访问未授权的控制器操作。我希望为您提供有关实施的想法。

This will guarantee that no unauthorized user accesses the controller action which is not authorized. I hope that gives you an idea about the implementation.

这篇关于如何动态手柄角色|在Symfony2的权限:限制使用动态角色功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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