繁体   English   中英

如何动态处理Symfony2中的角色|权限:使用动态角色限制功能

[英]How to dynamic handle roles|permissions in Symfony2: restrict functions with dynamic roles

这篇文章的目的是一种第二部分的这个职位,所以你可能要读得懂这个问题。 拥有该信息和上一篇文章的答案,并且还发现了这个有用的UserBundle ,可以帮助我举例说明rolesusers之间可能存在的Many To Many关系:

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

我的意思是,例如,我想将现有功能限制为已动态创建的ROLE_NEWROLE角色,因此在基础代码(原始源代码)上不存在,那么如何将现有功能限制为该新角色? 此处的文档为例:

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

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

上面的代码假定ROLE_ADMIN已经在某处以某种方式声明,但是如果我想通过安全组件将新的ROLE_NEWROLE添加到该函数中怎么办? 我是否需要一直触摸我的代码? 这一点都不好笑,所以我想知道您对这个话题的看法。

正如我们之前讨论的那样,您需要实现EventListener ,它将侦听onKernelRequest

用简单的英语来说,这意味着在授予对原始控制器的访问权限之前, 所有控制器动作将首先执行onKernelRequest 这样您就不必写

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

在每个控制器动作中。

现在,取决于您要使用此方法执行的操作。 我的方法是制作一个将ROLEROUTE关联的表。 该表将相对较大,因为您必须包括要授予所有ROUTES访问权限的所有ROLES

表结构可以是这样的:

ACCESSID      ROLENAME                ROUTENAME
    1       ROLE_NEWUSER       contacts_lookup_homepage
    2       ROLE_SUPER_USER    contacts_lookup_homepage

根据此表,只有ROLE_NEWUSERROLE_SUPER_USER才有资格访问路线contacts_lookup_homepage

现在,仅允许这些角色访问contacts_lookup_homepage路由。 现在,在onKernelRequest上,您要做的就是查询该表并检查该角色与该路由是否匹配。 您可以使用此方法访问两者。 这些路由与您在每条路由的routing.yml文件中定义的路由相同。 如果不确定,它看起来像这样:

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

现在终于可以在onKernelRequest中执行以下操作:

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 }

这将确保没有未经授权的用户访问未经授权的控制器操作。 希望您能对实现有所了解。

暂无
暂无

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

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