2015-12-11 108 views
1

本文旨在成爲this後的第二部分,因此您可能需要閱讀它才能理解此問題。有了這樣的信息,並從以前的帖子,並回答已經發現this有用UserBundle這有助於我作爲一個例子來說明可能的關係,rolesusers之間Many To Many我可能會問:如何在Symfony2中動態處理角色|權限:使用動態角色限制功能

  • 我有動態的角色和現在我如何使用這些新的ROLES

我的意思,比如我要限制一個存在的功能作用ROLE_NEWROLE已動態創建,因此不存在對基礎代碼(原始資料),然後我怎麼限制一個存在的功能那新角色?就拿文檔here爲例:

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; 

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

上面的代碼假定ROLE_ADMIN已經某處,不知何故已宣告但如果我想通過安全組件新ROLE_NEWROLE添加到該功能是什麼?我是否需要隨時觸摸我的代碼?這根本不好笑,所以我想知道你對這個話題的看法。

+0

對不起,我不明白你的問題。你在這裏談論什麼存在的功能?我不清楚你到底想做什麼。你能更具體地瞭解這個問題嗎? –

+0

另外我沒有看到你提到的這個包的任何文檔。該軟件包與原始FOS/UserBundle相比還有哪些額外功能? –

+0

@DipenShah你的第一個懷疑看看OP我做了一些改進,我指的是'安全'組件。對於第二個Bundle沒有提供任何方法來看看如何管理獨立於'users'的'roles'和一個可能的方式來加入它們 – ReynierPM

回答

1

正如我們談到這個before,你需要實現EventListener這將聽你的onKernelRequest

用簡單的英語,這意味着您的控制器操作的全部將首先執行onKernelRequest,然後才允許訪問原始控制器。所以這樣你不必寫

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

在每個控制器的行爲。

現在,它取決於你想要在這個方法中做什麼。我的方法是製作一張表,將ROLEROUTE相關聯。這張表格會比較大,因爲您必須包含所有ROLES,您想要訪問所有ROUTES

表結構可以是這樣的:

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 } 

這將保證沒有未經授權的用戶訪問未經授權的控制器操作。我希望能給你一個關於實現的想法。

+0

它的確如此,謝謝,如果在編碼上出現任何問題,我會在這裏復出,但現在我明白你的解釋背後的想法 – ReynierPM

+0

歡迎你。當然。 –