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