Как я могу добавить «роли» на «путь» динамически в Symfony2?

Я новичок в Symfony2, хотя уже много лет разрабатываю с PHP (ZF1, ZF2, CakePHP).

В SF2 у меня следующий сценарий, согласно документации самого сайта:

security:
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_ADMIN }

Мне нужно вручную добавить каждый «путь» и «роли», которые могут получить доступ к этому «пути».
Как я могу сделать это динамически?
Как RBAC на Yii2:

введите описание изображения здесь

Есть ли готовый комплект или что-то в собственной документации SF2, позволяющее это сделать? В качестве гипотетического примера:

security:
access_control:
type: dynamically

PS: Простите модераторы, я не знаю, как это спросить. Пожалуйста, помогите мне улучшить мой вопрос.

2

Решение

Если вы хотите упростить добавление ролей, вы можете использовать аннотации.

Ваш вопрос требует динамической безопасности, которая сложна. Маршруты и все роли компилируются на этапе прогрева кэша. Итак, чтобы это работало, вам сначала нужно сохранить динамические значения. База данных будет хорошим вариантом для этого. Здесь я только покажу, как проверять роли, фактическую манипуляцию ролями, которую я оставлю вам.

Самый простой способ — внедрить проверку авторизации в ваш контроллер.

services:
acme_controller:
class:     "AcmeDemoBundle\Controller"arguments: ["@security.authorization_checker"]

Затем проверьте роли в действии (ях):

public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
}

public function listAction()
{
$role = /* load your role here */;
if (false === $this->authorizationChecker->isGranted($role)) {
throw new AccessDeniedException();
}

// ...
}

Выше приведено дублирование кода, если вы хотите его во многих контроллерах, так что вы также можете создать избиратель:

services:
acme.route.voter:
class: AcmeDemoBundle\RouteVoter
arguments:
- @security.role_hierarchy
public: false
tags:
- { name: security.voter, priority: 300 }

Пример:

public function __construct ( RoleHierarchyInterface $roleHierarchy )
{
$this->roleVoter   = new RoleHierarchyVoter( $roleHierarchy );
}

public function vote ( TokenInterface $token, $object, array $attributes )
{
if ( !$object instanceof Request ) {
return VoterInterface::ACCESS_ABSTAIN;
}

$requestUri = $object->getPathInfo();

if ( isset($this->votes[ $requestUri ]) ) {
return $this->votes[ $requestUri ];
}

$roles = /* load your roles */;

return $this->votes[ $requestUri ] = $this->roleVoter->vote( $token, $object, $roles );
}

Другим методом будет заменить router сервис с вашей собственной реализацией. Это подход, принятый моим CMF Bundle.

1

Другие решения

Вы можете динамически управлять отношением роли / маршрута следующим образом:

Вы создаете слушатель на ядре

<service id="toto.security.controller_listener" class="Administration\SecurityBundle\EventListener\SecurityListener">
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController" />
<argument type="service" id="service_container" />
</service>

и после того, как в слушателе вы реализуете этот метод

public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller)) {
return;
}$request = $event->getRequest();

$baseUrl = $request->getBaseUrl();
$requestUri = $request->getRequestUri();
$route = str_replace($baseUrl, "", $requestUri);
//you put your check logic
//you can implement a relation beetween routes  and roles/ users in database etc. you got the entire control on what you do
if(!$this->accessMananager->isGrantAccess(User $user, $route)){
throw new AccessDeniedException("blah blah blah")
}}

так как этот слушатель всегда будет вызываться перед любым вашим контроллером, рассмотрите возможность создания системы кеша

1

По вопросам рекламы [email protected]