Работа с несколькими уровнями ролей

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

Например, менеджер имеет полный доступ в своем отеле, но доступ только для чтения в другом отеле.
Бывший:

{
    ["organization":"paris","roles":[ADMIN,ROOT]],
    ["organization":"london","roles":[READ]]
}

Как я могу справиться со многими уровнями ролей в организациях?
Я читал кое-какую документацию в symfony о избирателях и ролях, но ничего о ролях в своего рода группах.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
0
173
2

Ответы 2

Избиратель - это путь

// src/Security/PostVoter.php
namespace App\Security;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

class OrganisationVoter extends Voter
{
    // these strings are just invented: you can use anything
    const READ= 'READ';
    const EDIT = 'EDIT ';

    protected function supports($attribute, $subject); bool //todo
    protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
    {
        // [...] check class like documentation
        $organisation= $subject;

        switch ($attribute) {
            case self::READ:
                return $this->canView($organisation, $user);
            case self::EDIT:
                return $this->canEdit($organisation, $user);
        }
    }

    private function canView(Organisation $organisation, User $user)
    {
        //here your logic if your user has the same organisation
    }

    private function canEdit(Organisation $organisation, User $user)
    {
        //here your logic if your user has the same organisation than the one in parameter and the good level of right (admin, root)
    }
}

Затем в вашем контроллере (или ветке или где угодно)

    if ($this->security->isGranted(OrganisationVoter::EDIT, $organisation)) {
        return true;
    }

В том, что вы описываете, написано «управление доступом на основе атрибутов». помогает вам внедрить/отделить авторизацию от приложения/API, которое вы хотите защитить. Это означает, что вы можете разрабатывать функциональные возможности независимо от логики авторизации.

Существует несколько стандартов, а именно XACML и АЛЬФА (сокращенный язык для авторизации).

Вот как выглядит архитектура:

XACML Architecture

  • точка применения политики (PEP) перехватывает бизнес-поток и создает запрос на авторизацию, который отправляет на PDP.
  • Точка принятия решения о политике (PDP) оценивает входящий запрос в соответствии с политиками, с которыми он был настроен. В конечном итоге он возвращает решение PEP.
  • PDP может использовать точки информации о политике (PIP) для извлечения отсутствующих метаданных (отдел пользователя, роль, местоположение; отдел ресурса, владелец...)

Предыдущий ответ заставляет вас реализовать избиратель. Это очень хрупко и потребует кодирования и регулярного обновления по мере изменения ваших требований. В ALFA этого делать не нужно. Вы просто пишете политики на простом старом английском языке, которые используют интересующие вас атрибуты. Например:

  • Пользователь с ролью == "manager" может выполнять действие == "view" над объектом типа == "hotel"
  • Пользователь с ролью == «менеджер» может выполнять действие == «редактировать» над объектом типа == «гостиница», если hotel.owner == user.name

Другие вопросы по теме