Вопрос по архитектуре приложения. Проверка прав доступа.

12
Solmyr
На сайте с 10.09.2007
Offline
501
681

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

В общем-то такой сущности как "роли" по большому счету нет кроме роли "администратор" у которого есть права на все. Обычно юзверь имеет права доступа к "своим" объектам, а кроме того есть конкретные списки или правила, по которым есть права доступа к чужим объектам. Потому RBAC тулить вроде бы не очень обоснованно.

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

1. В класс user:

user.has_permission(object, op_name);

2. В класс-контроллер объекта с которым производится действие:

object.has_permission(user, op_name);

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

perm_controller.check_permission(object, user, op_name);

Вопрос к тем кто сталкивается с разработкой архитектуры приложений - как лучше?

Gerga
На сайте с 02.08.2015
Offline
94
#1

Solmyr, сделать 3 вариантом, но правила расписать в других Voter классах, чтобы не раздувать этот глобальный инстанс методами, нап. его можно назвать "Security". Сделав таким образом, вы в любом классе можете добавить метод has_permission, который будет вызывать методы Security.

SeVlad
На сайте с 03.11.2008
Offline
1609
#2
Solmyr:
Потому RBAC тулить вроде бы не очень обоснованно.

Почему нет если:

Solmyr:
Нужно проверять право юзверя совершать те или иные действия над объектом.

RBAC же как раз и служит для управления возможностями ролей.

Тем более если набор "тех или иных действий над объектом" будет разный для родей/юзеров. Но тогда надо еще этим действиями надо задавать capabilities.

Делаю хорошие сайты хорошим людям. Предпочтение коммерческим направлениям. Связь со мной через http://wp.me/P3YHjQ-3.
IL
На сайте с 20.04.2007
Offline
435
#3
Solmyr:
perm_controller.check_permission(object, user, op_name);

Ну.. только не контроллер =)

Вообще, мне логичным кажется подход (можно пробежаться по реализации RBAC в современных фреймворках)

if ($user->can($permission, $params)) ...

А логику прятать в некий Gate/AuthManager

 checkAccess ( $userId, $permissionName, $params = [] )

А случаи с ownPost и прочими "своё-чужое" реализовывать через правила вроде:


class AuthorRule extends Rule
...
public function execute($user, $item, $params)
{
return isset($params['post']) ? $params['post']->createdBy == $user : false;
}

Yii2 - https://www.yiiframework.com/doc/guide/2.0/ru/security-authorization#ispolzovanie-pravil

или: (laravel)

Gate::define('update-post', function ($user, $post) {
return $user->id == $post->user_id;
});

Фильтровать можно как в базовом контроллере, так и непосредственно в action-е.

... :) Облачные серверы от RegRu - промокод 3F85-3D10-806D-7224 ( http://levik.info/regru )
S
На сайте с 30.09.2016
Offline
469
#4
Solmyr:
В общем-то такой сущности как "роли"

Значит, надо сделать. И получится – в варианте 2 проверка варианта 1.

Отпилю лишнее, прикручу нужное, выправлю кривое. Вытравлю вредителей.
IL
На сайте с 20.04.2007
Offline
435
#5
Sitealert:
Значит, надо сделать. И получится – в варианте 2 проверка варианта 1.

На самом деле, они есть.. Даже если явно не обозначены.. Как минимум...

- администратор

- авторизованный пользователь

- гость

Просто перейти от проверки вроде

if (is_admin())

к более абстрактному и расширяемому..

Solmyr, на самом деле, можно любым из вариантов (и их комбинацией) к чему-то интересному прийти.. Главное - начать.. ))

S
На сайте с 30.09.2016
Offline
469
#6
ivan-lev:
На самом деле, они есть.. Даже если явно не обозначены.. Как минимум...
- администратор
- авторизованный пользователь
- гость

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

Solmyr
На сайте с 10.09.2007
Offline
501
#7
ivan-lev:
Solmyr, на самом деле, можно любым из вариантов (и их комбинацией) к чему-то интересному прийти.. Главное - начать.. ))

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

---------- Добавлено 13.10.2019 в 22:53 ----------

SeVlad:
Почему нет если:

Потому что фактически один юзер - одна роль. Для каждого юзверя список объектов к которым есть доступ - разный. Причем даже не только просто юзер имеет доступ к своим объектам, а к своим "плюс" - где плюс просто разный список для разных юзеров.

Gerga
На сайте с 02.08.2015
Offline
94
#8
Solmyr:
Сейчас склоняюсь в пользу второго варианта, но пока еще не склонился окончательно.

Сделав вариантом 2, у вас получатся огромные классы-контроллеры с бизнес-логикой, это плохо. В хорошей архитектуре контроллеры должны быть тонкими и должны использовать методы Services-классов (3 вариант).

---------- Добавлено 13.10.2019 в 23:06 ----------

Solmyr:
Но вот при очередных расширениях функционала, стали меня терзать сомнения что это не совсем верно.

Что именно?

IL
На сайте с 20.04.2007
Offline
435
#9
Solmyr:
А комбинации и зоопарки методов - это не хорошо. Потом баги стадами ходить будут.

Под комбинацией имел в виду, что логика

$user->can('update-post',$post)
user.has_permission(object, op_name);

реализуется путём чего-то похожего на:

Gate::check($user, 'update-post', $post)
perm_controller.check_permission(object, user, op_name);

Первое более логично.. второе - суть.

S
На сайте с 30.09.2016
Offline
469
#10
Solmyr:
Потому что фактически один юзер - одна роль. Для каждого юзверя список объектов к которым есть доступ - разный.

Да ладно! Это ничего не меняет, по сути. Список объектов - это и есть список ролей, фактически. Бахаем в БД для каждого юзера сериализованный объект или массив, например, – а при выяснении прав на совершение действий проверяем наличие необходимого элемента.

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий