Обрабатывать многоуровневые роли - PullRequest
0 голосов
/ 14 марта 2019

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

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

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

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

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Избиратель - это путь, по которому нужно идти

// 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;
    }
0 голосов
/ 02 мая 2019

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

Существует несколько стандартов - XACML и ALFA (сокращенный язык для авторизации).

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

XACML Architecture

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

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

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