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

Я работаю над проектом Symfony 2.8, и у меня есть сомнения относительно прав пользователей / групп / ролей. Существует несколько способов обработки пользователей и групп, например, SonataUser поверх SonataAdmin и в последнее время EasyAdmin, но у всех из них отсутствует управление правами ROLE |, и это точно мое сомнение: как правильно их обрабатывать? Да, я знаю, что мне нужно написать их в security.yml но я не знаю, смогу ли я сохранить его в БД (где-то), а затем читать оттуда. У меня есть исследование об этом, и я нашел ACL, избирателей и т. Д., Но вместо того, чтобы ясно понять, что исследование меня очень запутывает, поэтому мне нужно оттолкнуть от людей здесь. Затем:

  • Как бы вы справились с этим?
  • Любой пример на уровне кода? (Я предпочитаю видеть что-то другое, кроме слов, чтобы получить всю суть)
  • Являются ли ROLES именами как разрешениями?

Обновление: улучшите вопрос

Я хочу иметь отношение ManyToMany между users и roles и, возможно, groups и roles . Я думаю, что, поскольку SonataUserBundle справляется с этим, создавая роли столбцов в таблице user и назначая много ролей каждому пользователю, даже создавайте новые, если я не ошибаюсь, но как насчет того, если я хочу создать столько роли, сколько могу не назначая их пользователю, а затем добавляйте много ролей для пользователя даже в группу?

Как бы Вы это сделали?

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

Вы можете добавлять новые роли в FOSUserBundle на ходу. Вам не нужно сначала добавлять его в файл security.yml .

Для этого вы можете сделать что-то вроде этого:

 $user = new User(); $user->addRole('ROLE_NEWUSER'); //Role Name should begin with 'ROLE_' 

или в вашем контроллере вы можете получить текущий или любой пользователь

 $this->getUser(); $user->addRole('ROLE_NEWUSER'); //Role Name should begin with 'ROLE_' 

Это отвечает вашей первой и второй части.

Для третьей части роли могут использоваться как разрешения. Ранее я реализовал структуру, когда я ограничивал доступ к страницам на основе роли пользователя, также ограничивая, какие данные они могут изменять в зависимости от их роли.

ОБНОВЛЕНИЕ Я реализовал прослушиватель событий для этого, который будет прослушивать все запросы ядра, которые вызывают onKernelRequest . Я частично выполнил управление доступом на стороне SQL, так как у меня есть свои роли, хранящиеся на стороне SQL, но вы можете сделать то же самое на стороне сервера. Мой прослушиватель событий выглядел так: (Это урезанная версия того, что у меня есть)

 class TokenListener { protected $em; protected $token_storage; protected $templating; protected $router; protected $resolver; public function __construct($em,TokenStorageInterface $token_storage, TwigEngine $templating, Router $router, ControllerResolver $resolver) { $this->em = $em; $this->token_storage = $token_storage; $this->templating = $templating; $this->router = $router; $this->resolver = $resolver; } 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 if(!is_int(array_search($route, $routeArr)) && false) { $userRoles = $this->token_storage->getToken()->getUser()->getRoles(); if(!in_array('ROLE_NEWUSER', $userRoles)) { $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 } 

ОБНОВЛЕНИЕ Чтобы ответить на часть обновления вопроса, что вы можете сделать, это иметь другой объект roles и вы можете заранее заполнить роли, которые вы хотите, а затем установить отношение «один ко многим» к исходной таблице « User . Затем вы можете иметь что-то вроде prePersist or preUpdate Doctrine Lifecycle Events для проверки при добавлении нового, если роль уже существует в вашей роли. Это должно точно решить вашу проблему. Все это будет включать в себя небольшую настройку. Нет прямого способа сделать это.

Это зависит от того, как вы хотите это реализовать.

Один подход:

Внедрите UserProviderInterface в loadByUsername (где вы загружаете роли и разрешения) реализацию UserInterface (ваш User ).

Затем VoterInterface . Зарегистрируйте это как сервис с тегом security.voter и укажите его как поставщика в security.yml. Переопределите функцию vote чтобы оценить User вы загрузили для разрешений (и, возможно, роли тоже), из TokenInterface который является первым аргументом этой функции.