Как динамически управлять ролями | разрешениями в Symfony2: ограничить функции динамическими ролями

Этот пост должен быть своего рода второй частью этого сообщения, поэтому вам, возможно, придется прочитать его, чтобы понять этот вопрос. Имея эту информацию и ответ от предыдущего сообщения, а также обнаружив этот полезный UserBundle, который помогает мне в качестве примера проиллюстрировать возможные отношения как « Many To Many между roles и users я могу спросить:

  • У меня динамические роли, и теперь, как я использую эти новые 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 к этой функции через компонент безопасности? Нужно ли мне постоянно касаться моего кода? Это совсем не смешно, поэтому я хочу узнать ваше мнение по этой теме.

Solutions Collecting From Web of "Как динамически управлять ролями | разрешениями в Symfony2: ограничить функции динамическими ролями"

Поскольку мы говорили об этом раньше , вам нужно реализовать EventListener который будет прослушивать ваш onKernelRequest .

На простом английском языке это означает, что все ваши действия с контроллером будут выполняться сначала на onKernelRequest прежде чем давать доступ к исходному контроллеру. Таким образом, вам не придется писать

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

в каждом действии контроллера.

Теперь, это до вас, что вы хотите сделать в этом методе. Мой подход заключался в создании таблицы, которая связывает ROLE с ROUTE . Эта таблица будет сравнительно большой, потому что вы должны включить все ROLES которые хотите предоставить доступ ко всем 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 все, что вы сделаете, – это запросить эту таблицу и проверить, совпадает ли с этой ролью этот маршрут. У вас есть доступ к обоим методам. Эти маршруты такие же, как те, которые вы определяете в файле маршрутизации.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 } 

Это гарантирует, что неавторизованный пользователь не получит доступ к действию контроллера, которое не разрешено. Надеюсь, это даст вам представление об осуществлении.