Я работаю над проектом Symfony 2.8, и у меня есть сомнения относительно прав пользователей / групп / ролей. Существует несколько способов обработки пользователей и групп, например, SonataUser поверх SonataAdmin и в последнее время EasyAdmin, но у всех из них отсутствует управление правами ROLE |, и это точно мое сомнение: как правильно их обрабатывать? Да, я знаю, что мне нужно написать их в security.yml
но я не знаю, смогу ли я сохранить его в БД (где-то), а затем читать оттуда. У меня есть исследование об этом, и я нашел ACL, избирателей и т. Д., Но вместо того, чтобы ясно понять, что исследование меня очень запутывает, поэтому мне нужно оттолкнуть от людей здесь. Затем:
Обновление: улучшите вопрос
Я хочу иметь отношение ManyToMany
между users
и roles
и, возможно, groups
и roles
. Я думаю, что, поскольку SonataUserBundle
справляется с этим, создавая роли столбцов в таблице user
и назначая много ролей каждому пользователю, даже создавайте новые, если я не ошибаюсь, но как насчет того, если я хочу создать столько роли, сколько могу не назначая их пользователю, а затем добавляйте много ролей для пользователя даже в группу?
Как бы Вы это сделали?
Вы можете добавлять новые роли в 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
который является первым аргументом этой функции.