Sonata Admin: isGranted() всегда возвращает true в классе Admin, но правильное логическое значение в шаблоне

Я использую SonataAdminBundle и SonataUserBundle в проекте Symfony 2. Установленные пакеты:

$ composer show | grep symfony
friendsofsymfony/rest-bundle             1.7.7              This Bundle provides various tools to rapidly develop RESTful API's with Symfony
friendsofsymfony/user-bundle             v1.3.6             Symfony FOSUserBundle
symfony/assetic-bundle                   v2.8.0             Integrates Assetic into Symfony2
symfony/css-selector                     v2.8.6             Symfony CssSelector Component
symfony/dom-crawler                      v2.8.6             Symfony DomCrawler Component
symfony/monolog-bundle                   2.11.1             Symfony MonologBundle
symfony/polyfill-apcu                    v1.1.1             Symfony polyfill backporting apcu_* functions to lower PHP versions
symfony/polyfill-mbstring                v1.1.1             Symfony polyfill for the Mbstring extension
symfony/swiftmailer-bundle               v2.3.11            Symfony SwiftmailerBundle
symfony/symfony                          v2.7.13            The Symfony PHP framework

$ composer show | grep sonata
sonata-project/admin-bundle              2.3.10             Symfony SonataAdminBundle
sonata-project/block-bundle              2.2.15             Symfony SonataBlockBundle
sonata-project/cache                     1.0.7              Cache library
sonata-project/core-bundle               2.3.11             Symfony SonataCoreBundle
sonata-project/doctrine-extensions       1.0.2              Doctrine2 behavioral extensions
sonata-project/doctrine-orm-admin-bundle 2.3.4              Symfony Sonata / Integrate Doctrine ORM into the SonataAdminBundle
sonata-project/easy-extends-bundle       2.1.10             Symfony SonataEasyExtendsBundle
sonata-project/exporter                  1.4.1              Lightweight Exporter library
sonata-project/google-authenticator      1.0.2              Library to integrate Google Authenticator into a PHP project
sonata-project/user-bundle               2.2.5              Symfony SonataUserBundle

Роли в конфигурационном файле security.yml:

role_hierarchy:
    ROLE_ADMIN:       [ROLE_USER, ROLE_SONATA_ADMIN]
    ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

Войдя в систему с пользователем, у которого есть только ROLE_ADMIN, следующие дампы из моего класса UserAdmin:

dump($this->isGranted('ROLE_ALLOWED_TO_SWITCH'));
dump($this->isGranted('ROLE_BLA_BLA_BLA'));
dump($this->isGranted('ROLE_USER'));

печать на панели инструментов Symfony (в среде dev)

true
true
true

А если я помещу дампы в переопределенный шаблон Сонаты, такой как app/Resources/SonataAdminBundle/views/CRUD/[anytemplate].html.twig,

{{ dump(is_granted('ROLE_ALLOWED_TO_SWITCH')) }}
{{ dump(is_granted('ROLE_BLA_BLA_BLA')) }}
{{ dump(is_granted('ROLE_USER')) }}

возвращаются правильные значения.

false
false
true

Я влез в это, потому что эта строка здесь, в SonataUserBundle, не имела никакого эффекта: https://github.com/sonata-project/SonataUserBundle/blob/3.x/Admin/Model/UserAdmin.php#L95

Использование isGranted() описано здесь: http://symfony.com/doc/current/bundles/SonataAdminBundle/reference/security.html#usage

Я что-то не так делаю или это баг?

Изменить:

Благодаря комментарию @mickadoo я заметил, что у меня есть обработчик по умолчанию sonata.admin.security.handler.noop, который, как говорят, всегда возвращает true, что бы это ни значило. Я установил его с sonata.admin.security.handler.role и создал несколько ролей (ROLE_SONATA_USER_ADMIN_USER_LIST и ROLE_SONATA_USER_ADMIN_USER_VIEW), и теперь он возвращает правильное значение для $this->isGranted('LIST') или $this->isGranted('VIEW'), но всегда возвращает false для $this->isGranted('ROLE_USER') или $this->isGranted('ROLE_ALLOWED_TO_SWITCH').

Как я могу проверить эти роли?


person VMC    schedule 24.05.2016    source источник
comment
Установили ли вы для access_decision_strategy значение единодушного, как указано здесь? symfony.com/doc/current/bundles/SonataAdminBundle/reference/   -  person mickadoo    schedule 24.05.2016
comment
Благодарю вас! Это мало что изменило, но помогло мне заметить, что я использую обработчик по умолчанию sonata.admin.security.handler.noop. Я отредактировал вопрос, чтобы предоставить больше информации.   -  person VMC    schedule 25.05.2016
comment
Приятно слышать, что это помогло вам. Как я уже сказал, у меня нет опыта работы с сонатой, но я не вижу никаких способов проверки чисто ролей на странице документации. Вы пробовали $this->get('security.authorization_checker')->isGranted('ROLE_USER'))? Если вы просто хотите проверить, есть ли у пользователя роль, вы всегда можете создать службу, используя RoleHierarchy, чтобы проверить, содержит ли доступная роль роль, которую вы хотите проверить, но, возможно, это не самый чистый способ. Если бы вы могли отладить и проверить, какой из AccessDecisionManager избирателей возвращает false, это может помочь.   -  person mickadoo    schedule 25.05.2016


Ответы (3)


Общие роли, не являющиеся сущностью, такие как ROLE_USER, ROLE_ADMIN, ROLE_SUPER_ADMIN, ROLE_{CUSTOM_STRING}, следует проверять с использованием контекста безопасности Symfony по умолчанию.

В классе Admin:

$securityContext = $this->getConfigurationPool()->getContainer()->get('security.context');

if ($securityContext->isGranted('ROLE_USER')) {
    // Your PHP code here
}

В шаблоне Twig:

{% if is_granted('ROLE_USER') %}
    Your HTML/Twig content here.
{% endif %}

Роли действий сущностей, такие как ROLE_SONATA_USER_ADMIN_USER_LIST, ROLE_SONATA_USER_ADMIN_USER_VIEW, ROLE_{CUSTOM_SONATA_ADMIN_SERVICE_NAME}_{ACTION}, можно проверить с помощью помощника администратора Sonata или контекста безопасности Symfony.

В классе Admin:

// Using Symfony security context
$securityContext = $this->getConfigurationPool()->getContainer()->get('security.context');

if ($securityContext->isGranted('ROLE_SONATA_USER_ADMIN_USER_LIST')) {
    // your code here
}

// Using Sonata helper for shorter syntax
if ($this->isGranted('LIST')) {
    // your code here
}

В шаблоне Twig:

<!-- Using Symfony security context -->
{% if is_granted('ROLE_SONATA_USER_ADMIN_USER_LIST') %}
    Your HTML/Twig content here.
{% endif %}

<!-- Using Sonata helper -->
{% if admin.isGranted('LIST') %}
    Your HTML/Twig content here.
{% endif %}
person VMC    schedule 26.05.2016
comment
При использовании $securityContext = $this->getConfigurationPool()->getContainer()->get('security.context'); в классе администратора я получаю сообщение об ошибке: You have requested a non-existent service "security.context". Пожалуйста, сообщите - person Mentos93; 21.10.2016
comment
Не берите в голову. Я понял. security.context используется до Symfony 2.5. Начиная с Symfony 2.6 служба security.context устарела, и теперь мы должны использовать вместо нее security.authorization_checker. Как это; $securityContext = $this->getConfigurationPool()->getContainer()->get('security.authorization_checker'); - person Mentos93; 21.10.2016
comment
Я получаю эту ошибку при попытке использовать author_checker в классе администратора. Хранилище токенов не содержит токена аутентификации. Одной из возможных причин может быть отсутствие настройки брандмауэра для этого URL-адреса в . (который импортируется из app/config/routing.yml). Убедитесь, что есть загрузчик, поддерживающий тип sonata_admin. а токен NULL, что я делаю не так? - person Laurentiu; 17.10.2017

это сработало для меня в администраторе сонаты и Symfony 4:

/**
 * @param string $role
 * @return bool
 */
protected function checkUserHasRole(string $role): bool
{

    $securityContext = $this->getConfigurationPool()->getContainer()->get('security.authorization_checker');
    try {
        return $securityContext->isGranted($role);
    } catch (AuthenticationCredentialsNotFoundException $e) {
        return false;
    }
}
person Sebastian Viereck    schedule 11.02.2019
comment
Вопрос был о проекте Symfony 2 (я обновил его, чтобы отразить это). Ваш ответ может быть полезен для тех, кто использует Symfony 4. Спасибо за публикацию. - person VMC; 24.02.2019

Сейчас я работаю над проектом, и кажется, что isGranted делает это в классах администратора. Обходной путь, который я нашел, это в классе Admin:

if ($this->getContainer()->get('security.token_storage')->getToken()->getUser()->getRoles()[0] == 'ROLE_EMPLOYEE') {}

Он возвращает роли (без наследования), которые вы назначили при создании пользователя. Вам, конечно, нужно будет обеспечить наследование, поэтому вам придется перечислить все роли, которые вы хотите разрешить или запретить, в зависимости от того, что меньше в списке. Убедитесь, что getUser() не пуст, а getRoles() возвращает массив.

person Rishi    schedule 25.01.2018