Symfony 4 Voters - вопросы о ролях и разрешениях

Я начал работать над системой голосования, чтобы защитить свои URL-адреса, и у меня есть много вопросов.

Во-первых, я не знаю, нужно ли мне работать с «ролями» или «разрешениями».

Под «ролями» я подразумеваю что-то вроде Role_User, Role_Manager и т. Д. А под «разрешениями» я имею в виду что-то вроде «Access_users», «Edit_User», «Add_User» и т. Д.

Я прав?

Если да, я хотел бы проверить разрешения в моих избирателях, чтобы контролировать доступ к URL-адресу, если у меня нет объекта для управления.

Пример

/**
 * @Route("/", name="list")
 * @Security("is_granted('ROLE_ADMIN') or is_granted('PERM_ACCESS_SERIES')")
 */
public function list()
{
    $series = $this->seriesService->findAll();

    return $this->render('backend/series/list.html.twig', [
        "series" => $series
    ]);
}

В этом случае я хочу проверить, есть ли у пользователя роль ROLE_ADMIN или разрешение PERM_ACCESS_SERIES, но я не знаю, как это сделать в моих голосующих.

Для информации, «ROLE_ADMIN» установлен в моей конфигурации security.yaml, но я хотел бы сделать эти роли динамическими, чтобы иметь возможность создавать роли (и назначать разрешения для роли?).

В моем классе избирателя, когда я контролирую документ, я проверяю владельца и других пользователей, которые могут управлять документом, но когда я не передаю документ, я действительно не знаю, что делать.

Просто получите разрешения пользователя и проверьте, есть ли у них запрашиваемое разрешение. что-то подобное :

if (in_array($attribute, $user->getPermissions())) {
    return true;
}

На самом деле вот мой избиратель

 protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
    //ADMIN and SUPER_ADMIN can do anything they want !
    if ($this->decisionManager->decide($token, array(User::ROLE_ADMIN, User::ROLE_SUPER_ADMIN))) {
        return true;
    }

    $user = $token->getUser();
    if (!$user instanceof User) {
        // the user must be logged in. if not, deny access
        return false;
    }

    $series = $subject;
    switch ($attribute) {
        case self::PERM_ACCESS_SERIES:
            if (in_array($attribute, $user->getPermissions())) {
                return $this->canAccess($series, $user);
            }
            break;

        case self::PERM_ADD_SERIES:
            if (in_array($attribute, $user->getPermissions())) {
                return $this->canAdd($series, $user);
            }
            break;

        case self::PERM_EDIT_SERIES:
            if (in_array($attribute, $user->getPermissions())) {
                return $this->canEdit($series, $user);
            }
            break;

        case self::PERM_DELETE_SERIES:
            if (in_array($attribute, $user->getPermissions())) {
                return $this->canDelete($series, $user);
            }
            break;

        default:
            throw new \LogicException('This code should not be reached!');
            break;
    }

    return false;
}

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

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

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


person Etshy    schedule 16.08.2018    source источник


Ответы (1)


То, что вы говорите, роли и разрешения на вашем пути - одно и то же. Не нужно их различать. Вы можете думать о своем PERM, таком как ROLE_ACCESS_SERIES и так далее, это просто вопрос именования / соглашений, но с точки зрения Symfony это то же самое.

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

Теперь я буду говорить только о ролях.

Для динамических ролей ваш объект UserInterface имеет метод getRoles(), который не обязательно должен быть статическим, но может, например, загружать роли из базы данных / любого хранилища, которое вы хотите для каждого пользователя.

Для объекта, чтобы проверить разрешение. Например, ROLE_LIST_SERIES обычно не нуждается в каком-либо объекте для проверки разрешения, поэтому все в порядке без объекта, но ROLE_EDIT_SERIES, например, всегда должен иметь объект, который мы редактируем, означает, что если нет, мы генерируем исключение, и это означает, что мы где-то упускаем место, чтобы передать это.

Для меня, если мы возьмем, например, CRUD, у меня будут такие роли:

ROLE_ENTITY_MASTER:
    - ROLE_ENTITY_LIST
    - ROLE_ENTITY_EDIT
    - ROLE_ENTITY_ADD
    # and you continue what you need.

Преимущество этого в том, что, например, если я хочу предоставить кому-то полный доступ к чему-либо, мне просто нужно назначить одну роль, и если я хочу, чтобы кто-то ограничил, я даю ему только те роли, которые я хочу. Затем в моем getRoles() (на самом деле я загружаюсь из базы данных, так что это просто псевдокод).

getRoles() {
    return [ROLE_ADMIN, ROLE_ENTITY_MASTER2, ROLE_ENTITY_MASTER];
}
person M. Kebza    schedule 17.08.2018
comment
Большое спасибо, ваше первое предложение действительно помогло мне прояснить мои мысли. Я использую FOSUser, поэтому у меня уже есть getRoles и все остальные обязательные поля. но могу ли я сделать эту иерархию ролей (как вы сделали с ROLE_ENTITY_MASTER) динамически. Таким образом, я мог бы дать администратору возможность создавать собственные роли MASTER, которые наследуют роли permissions (или другие MASTER), которые им нужны. Или мне нужно сделать эту иерархию (чтобы создать роли MASTER для каждого из моих документов) в конфигурации (как в документе, с параметрами role_hierarchy), и она не может быть динамической? - person Etshy; 17.08.2018
comment
Я не пробовал выполнять роли динамически (потому что у меня они связаны с моими ресурсами, просто получил скрипт, который выгружает их в конфигурацию). Но я не вижу причин для вашего администратора создавать роли, потому что вы можете просто назначить больше ролей своим правилам, вместо того, чтобы создавать новые. - person M. Kebza; 18.08.2018
comment
Что ж, я хотел добавить возможность создания роли, которая наследует другие роли, чтобы упростить набор ролей для других пользователей. Например, администратор создает роль «обновления» с ролью обновления и просмотра, но не удаляет, и он может просто назначить роль «обновления» для пользователей. Но просто распределить все роли тоже может быть неплохо. Большое спасибо за вашу помощь, кстати. - person Etshy; 18.08.2018
comment
Для этого FOSUser имеет группы, вы назначаете роли группе (редактору), а затем назначаете эти группы пользователю. - person M. Kebza; 19.08.2018
comment
О, спасибо, не видел этого. Я посмотрю, как он может работать с избирателями. - person Etshy; 19.08.2018
comment
Это будет работать, это две вещи - группы, говорящие, какие у пользователя РОЛИ, избиратели, проверяющие, есть ли доступ у РОЛИ. - person M. Kebza; 19.08.2018
comment
Но мне нужно проверить роли во всех ролях групп пользователей? или будет работать проверка ролей пользователя? Вот что я должен искать. Большое спасибо за эти советы. - person Etshy; 20.08.2018
comment
FOSUser собирает роли из группы в вашем getRoles(), откуда вы собираете роли, зависит только от вашей getRoles функции в вашем пользователе. - person M. Kebza; 20.08.2018