簡體   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