Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何动态处理Symfony2中的角色|权限:使用动态角色限制功能_Php_Symfony_Security_Authentication_Authorization - Fatal编程技术网

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

Php 如何动态处理Symfony2中的角色|权限:使用动态角色限制功能,php,symfony,security,authentication,authorization,Php,Symfony,Security,Authentication,Authorization,这篇文章的目的是作为文章的第二部分,所以你可能需要阅读它来理解这个问题。有了这些信息和上一篇文章的答案,还发现了有用的UserBundle,这有助于我举例说明角色和用户之间可能存在的多对多关系,我可能会问: 我有动态角色,现在我如何使用这些新的角色 我的意思是,例如,我想将一个现有函数限制为rolerole\u NEWROLE,它是动态创建的,因此在基本代码(原始源代码)上不存在,那么如何将一个现有函数限制为该新角色?以单据为例: use Sensio\Bundle\FrameworkExt

这篇文章的目的是作为文章的第二部分,所以你可能需要阅读它来理解这个问题。有了这些信息和上一篇文章的答案,还发现了有用的UserBundle,这有助于我举例说明
角色
用户
之间可能存在的
多对多
关系,我可能会问:

  • 我有动态角色,现在我如何使用这些新的
    角色
我的意思是,例如,我想将一个现有函数限制为role
role\u NEWROLE
,它是动态创建的,因此在基本代码(原始源代码)上不存在,那么如何将一个现有函数限制为该新角色?以单据为例:

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

class PostController extends Controller
{
    /**
     * @Security("has_role('ROLE_ADMIN')")
     */
    public function indexAction()
    {
        // ...
    }
}
上面的代码假定
ROLE\u ADMIN
已在某处声明,但如果我想通过安全组件向该函数添加新的
ROLE\u NEWROLE
,该怎么办?我需要一直触摸我的代码吗?这一点也不好笑,所以我想知道你对这个话题的看法

正如我们所讨论的,您需要实现
EventListener
,它将侦听您的
onKernelRequest

简单地说,这意味着所有控制器操作将首先执行
onKernelRequest
,然后才能访问原始控制器。这样你就不用写了

/**
* @Security("has_role('ROLE_ADMIN')")
*/
在每个控制器动作中

现在,这取决于你想用这种方法做什么。我的方法是制作一个表,将
角色
路线
关联起来。此表将相对较大,因为您必须包含所有
角色
,以便访问所有
路由

表结构可以是这样的:

ACCESSID      ROLENAME                ROUTENAME
    1       ROLE_NEWUSER       contacts_lookup_homepage
    2       ROLE_SUPER_USER    contacts_lookup_homepage
contacts_lookup_homepage:
    path:     /Contacts/Lookup
    defaults: { _controller: ContactsLookupBundle:Default:index }
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:
    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 }
根据此表,只有
ROLE\u NEWUSER
ROLE\u SUPER\u用户
有资格访问路线
contacts\u lookup\u主页

通过这种方式,现在只允许那些角色访问
联系人\u查找\u主页
路由。现在在
onKernelRequest
上,您要做的就是查询这个表,并检查是否有与该角色匹配的路由。在这种方法中,您可以访问这两者。这些路由与您在每个路由的
routing.yml
文件中定义的路由相同。如果您不确定,它看起来像这样:

ACCESSID      ROLENAME                ROUTENAME
    1       ROLE_NEWUSER       contacts_lookup_homepage
    2       ROLE_SUPER_USER    contacts_lookup_homepage
contacts_lookup_homepage:
    path:     /Contacts/Lookup
    defaults: { _controller: ContactsLookupBundle:Default:index }
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:
    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 }
现在,最后在
onKernelRequest
中,您可以执行以下操作:

ACCESSID      ROLENAME                ROUTENAME
    1       ROLE_NEWUSER       contacts_lookup_homepage
    2       ROLE_SUPER_USER    contacts_lookup_homepage
contacts_lookup_homepage:
    path:     /Contacts/Lookup
    defaults: { _controller: ContactsLookupBundle:Default:index }
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:
    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 }
services.yml
可以是这样的:

ACCESSID      ROLENAME                ROUTENAME
    1       ROLE_NEWUSER       contacts_lookup_homepage
    2       ROLE_SUPER_USER    contacts_lookup_homepage
contacts_lookup_homepage:
    path:     /Contacts/Lookup
    defaults: { _controller: ContactsLookupBundle:Default:index }
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:
    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 }

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

对不起,我不太明白您的问题。你在这里说的是什么功能?我不清楚你到底想做什么。您能更具体地说明这个问题吗?另外,我没有看到您提到的关于这个捆绑包的任何文档。与原始FOS/UserBundle相比,此捆绑包增加了哪些额外功能?@DipenShah对于您的第一个疑问,请查看OP,我已经做了一些改进,我指的是
安全组件。对于第二个,Bundle没有提供任何东西,它只是一种查看如何独立于
用户管理
角色
,以及一种加入他们的可能方式的方法,这正是我之前提到的事件侦听器的用途。它做的工作和你想做的完全一样。我可以给你一个更好的选择,就是将你所有的路由和你想让它访问的角色存储在数据库中。这正是我一段时间前的要求,现在它成功地为我工作。我将在一段时间后发布答案。确实如此,谢谢,如果编码出现任何问题,我将回到这里,但现在我明白了你解释背后的想法