![]() |
Модераторы: skyboy, MoLeX, Aliance, ksnk |
![]() ![]() ![]() |
|
ksnk |
|
||||||||||||||
![]() прохожий ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 6855 Регистрация: 13.4.2007 Где: СПб Репутация: 96 Всего: 386 |
Приспичило заняться системой распределения прав в "общем" виде. Почитал документацию
на phpGACL, что-то понял, попробовал поставить. Тут оказалось, что сам дистрибутив весит 3 мб в архиве... Это меня вернуло на путь велосипедостроения ![]() Хотя идея, терминология и примеры навеяны phpGACL. Итак, предстоит реализовать объект RIGHT с методом can :
Предполагается, что функция RIGHT::can будет выполняться часто и должна работать быстро. Попробуем пофантазировать на эту тему... ![]() Так как система прав делается в "общем" виде, то кодирование прав числовыми константами не нужно. Обойдемся строковыми обозначениями. При устоявшейся базе данных можно будет оптимизировать ее, заменив некоторые поля перечисляемыми типами, совершенно прозрачно для приложения. Для того, кто не хочет читать доку по phpGACL - вот некоторые определения. Объекты, над которыми производятся действия, будем именовать AXO. Объекты, которые будут желать совершать действия - ARO. Что в реальности означают эти абревиатуры не имеет существенного смысла, однако желающие могут почитать доку. Объекты ARO/AXO организованы в дерево. "веточки" дерева - собственно объекты, узлы дерева - группы, хотя разница между ними только терминологическая. Самой распространенной операцией над этим деревом будет получение списка всех родителей объекта, так что реализация дерева должна обеспечить эффективность этой операции. списки прав будем хранить в соседней таблице rights:{ID_ARO as integer,ID_AXO as integer,`allow` as boolean,`what` as string,`level`}; Поле level будет представлять собой строковое значение "уровня" ID_ARO. Смысл поля - ниже. Итак, представим, что юзер username входит в группу USERS. Объект formname входит в группу "COMMON FORMS" и группе USERS разрешен доступ к "COMMON FORMS" для чтения и записи. сам факт наличия таких разрешений будет выглядеть как две строки в таблице (ID(USER),ID(COMMON FORMS), allow, 'read', level) (ID(USER),ID(COMMON FORMS), allow, 'write', level) процесс определения права будет выглядеть так вычисляем список родителей узла ARO username вычисляем список родителей узла AXO formname выполняем запрос
Тут мне начинает нравиться "Materialized Path"-дерево, так как этот самый путь, для генерации sql там уже храниться. Если юзер находится в нескольких группах, то у нас получится несколько путей. В принципе, можно свалить всю работу на SQL, просто объединив поля запятой. А можно мрачно implode(',',sort(unique(explode(',',implode(',',$paths)))))... Если будет доставать - придется строить еще одну таблицу со списком групп для юзера. Итак, мы определились с форматом таблицы ARO и AXO. Это "Materialized Path" с тройкой полей - {ID,"путь", "объект"}. Действия над объектом следует хранить в отдельной таблице action:{ID_AXO,'action'} таблица действий не участвует в операции вычисления прав, однако для админки она нужна. Убедимся на паре примеров, что результат запроса действительно даст нам унаследованые права. Для следующего примера возьмем схему из доки по phpGACL и ее слегка перерисуем. Обратите внимание, что для юзера Чуви введено "противоречивое" условие на доступ в машинный зал.
Объекты будут такими
часть таблицы с двигателями просто придумалась сама. Никуда вставить ее пока не получилось, не обращайте внимания ;) Табличка rights в этом случае будет выглядеть так
Первые пара значений в строке на самом деле являются ID соответствующих строк ARO и AXO, но для наглядности оставлены их символьные значения. посчитаем RIGHT::can('R2D2','маш.зал','доступ'). R2D2 состоит в группах ALL, Инженеры, Пассажиры В результате получится отсортированный список строк, нам нужна последняя.
RIGHT::can('Чуви','маш.зал','доступ'). Чуви - ALL, Команда,Инженеры
При выполнении запроса разрешения прав неожиданно не обнаружилось никакого противоречия, однако оно есть ;) Если бы группа Инженеры была подгруппой еще пары групп и уровень ее в иерархии был бы >2 То Чуви смог бы ходить в машзал. Впрочем, обнаружить противоречие и обозначить его для администратора - это проблема админки. Для рисования админки нам придется дописать объект RIGHT еще немного. Нужно будет уметь редактировать дерево ARO, уметь редактировать дерево AXO. В редакторе AXO нужно уметь указывать действия, которые можно совершать с объектом/группой. Указанные действия будут распространены на все ветки этой группы. Собственно распределение прав будет осуществлятся в редакторе ARO. На каждую строку дерева нужно подвесить добавление-удаление "объекта" с возможностью вычисления допустимых этим объектом действий, и комплект чекбоксов для запрета-разрешения этих действий, примерный макет можно посмотреть в любой os. О чем вообще этот пост? Мне показалось странным, что процедура разрешения прав для задачи распределения прав в "общем виде" решается с помошью одного запроса. Вероятно, это не с проста и я чего-то там недодумал. Может у кого появятся идеи? Это сообщение отредактировал(а) ksnk - 20.11.2011, 19:08 -------------------- Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! ![]() |
||||||||||||||
|
|||||||||||||||
baldina |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
проблема в том, что запрос возвращает Инженеров, а они вообще непричем при определении прав доступа Чуви.
вот сдесь ARO и AXO связаны, а результаты запроса как будто в запросе OR. при определении прав важна иерархия наследования относительно конкретного ARO, а не все AXO подряд |
||||
|
|||||
ksnk |
|
||||
![]() прохожий ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 6855 Регистрация: 13.4.2007 Где: СПб Репутация: 96 Всего: 386 |
Чуви в группе инженеров И в группе Команда. Это такой механизм включения юзеров в разные группы. В группе Команда у него еще отдельное запрещение . Так что запрос выдает правильно, и Инженеров тоже.
Для иерархии используется поле 'level'. Самое "глубокое", с точки зрения иерархии ARO, правило - победит. -------------------- Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! ![]() |
||||
|
|||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
||||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
помнится, я читал эту хрень и мне было плохо настолько, что Звёздные войны стали снится. (кстати, кто такой Ханук? тот голожаберный вместе с Ландо из 6-го эпизода?)
я разрешил себе ситуацию исключительно наглядным способом. у меня есть таблица меню, где указывают пути, названия и прочая атрибутика для построения. там же я указываю в одном поле набор прав для стандартных групп. какая бы общая задача не стояла, она всё равно вырождается в конкретику. группы типичные: гость, пользователь, участник, редактор, соредактор, модератор, администратор и разработчик. table_menu id;url;path;title...;access 15;forum;modules/forum/;Форум...;3,15,255,578,2045,4015,12456 как можно догадаться, каждое число - это набор битов для определённой типичной операции, коих у меня было 17 таким образом, уже при определении какой модуль на основании урла загружать, мы уже получаем для конкретного пользователя его права на этот модуль. дальше осталось только внедрить систему исключений, а это две таблицы: наследований и исключений причём у меня не было групп как таковых. просто создавался пользователь под именем "группа инженеров" и ей присвался необходимый набор прав для конкретного пункта меню "2045", а затем уже нужный нам пользователь Ханук получал наследование от пользователя "группа инженеров". причём я мог указать либо id модуля, либо 0 - как признак всех модулей соответственно, для типичных пользователей мы получаем всего один лишний запрос - к таблице наследований. для тех, у кого есть наследование - получаем ещё и запрос к исключениям доп плюсы - можно устроить ветвящуюся структуру наследований - но это даст больше запросов |
|||
|
||||
baldina |
|
||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
ksnk, похоже проблема с инженерами носит системный характер: максимальный уровень не может являться достаточным признаком. например, когда есть две строки с одинаковым уровнем, но противоположными разрешениями.
это означает, что 1. нужно различать конкретные разрешения пользователя от разрешений групп 2. порядок задания разрешений имеет значение это происходит потому, что имеется несколько деревьев, а не одна иерархия Добавлено @ 20:53 думаю достаточно добавить "признак листа", т.е. ввести в записи поле {'group', 'user'} и сортировать прежде всего по нему. тогда даже если инженеры находятся глубоко, например на уровне 5, результат будет правильный:
Добавлено через 9 минут и 44 секунды
![]() Это сообщение отредактировал(а) baldina - 20.11.2011, 20:53 |
||||||||
|
|||||||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
подумав еще немного, вижу что все не так просто.
сортировка по уровню вложенности нарушает порядок правил. так что неазнвчительное (с точки зрения пользователя) изменение структуры может приводить к иным разрешениям. это плохо. поглядим сюда: проблема в том, что Чуви (и другие) входят в структуру многократно. вероятно они должны быть ссылками. тогда будем иметь
и одной проблемой станет меньше. осталось решить вторую: не перемешивать уровни при сортировке, иначе (при отсутствии разрешений конкретного пользователя) результат будет меняться при изменении структуры. Это сообщение отредактировал(а) baldina - 20.11.2011, 21:09 |
|||
|
||||
ksnk |
|
||||
![]() прохожий ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 6855 Регистрация: 13.4.2007 Где: СПб Репутация: 96 Всего: 386 |
Вообще-то с точки зрения phpGACL - это не проблема, а пример неправильного заполнения таблицы прав, т.е. - ошибка администратора. Так что в принципе, можно при таких "противоречивых" установках наплевать на некорректное вычисление и просто информировать админа. Хотя, по некоторому размышлению, склоняюсь к тому, что phpGACL здесь что-то темнит ![]() В крайнем случае - можно детектировать противоречия в админке и не позволять админу обманывать самого себя. Если делать ссылки, а не явные поля, то получится слишком сложный sql и дополнительные таблицы. Вероятно, проще будет раскопировать установленные в одной строке разрешения-запреты на остальные строки того-же юзера... Надо будет еще подумать. В принципе - явно установленные права для конкретного юзера должны побеждать конкурентов, по логике вещей... Одна из основных целей - добиться минимального количества таблиц, пусть даже с небольшим ущербом эффективности, так как приложение не особенно нагруженное, но компактное.
Голожаберного из 6-го эпизода помню, но они с Облачного города улетали без всяких дополнительных инженеров, - Хан + Ландо... специально пересмотрел, так что кто такой Ханук - не знаю ![]() -------------------- Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! ![]() |
||||
|
|||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
||||
|
||||
ksnk |
|
||||||
![]() прохожий ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 6855 Регистрация: 13.4.2007 Где: СПб Репутация: 96 Всего: 386 |
Добрался таки до проекта и даже что-то понаписал.
В связи с этим возник вопрос. не попадался ли кому web-редактор чего-нибудь, который бы выглядел как regedit? Слева - дерево , справа - список свойств рассматриваемой ветки. Если с использованием jQuery - это совсем хорошо. Сейчас идет неторопливый процесс подпиливания админки. В результате может получится вполне себе самостоятельный проект, легко прикручиваемый в другое место. Получились следующие накладные расходы: Само дерево прав (хранящееся в одной таблице) с ветками объектов, пользователей и их групп с правами и действиями имеет смысл на существование только на момент администрирования его самого. Собственно процесс администрирования заканчивается нажатием на кнопку "скомпилировать", в результате чего появляются 2 "боевые таблицы", которые уже и определяют права пользователей. Итого 3 таблицы, причем одну из них можно сериализовать и прятать в параметры приложения, если очень нужно. Пока временнЫе рамки выполнения запросов получились приемлемыми? нужно будет сгенерировать достаточно большой пример и проверить скорость обработки на нем... Структура всех таблиц
таблица для хранения дерева для администрирования
"боевой" класс ( в принципе - ничего не мешает поставить его парой методов в другой объект)
Сама админка будет представлять из себя ajax приложение, которое получает предыдущее состояние дерева прав и сохраняет на сервере результат редактирования. Пока она сделана на базе jquery.dynatree.js. К сожалению этот самый динатрее предствляет из себя просто дерево с множеством не очень нужных мне наворотов, а мне виделся редактор в стиле regedit'а - слева дерево, справа - список свойств рассматриваемой ветки. -------------------- Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! ![]() |
||||||
|
|||||||
MoLeX |
|
|||
![]() Местный пингвин ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 4076 Регистрация: 17.5.2007 Репутация: 46 Всего: 140 |
ksnk, у меня немного изменились взгляды на эту тему, особенно после прочтения статьи http://habrahabr.ru/blogs/php/134557
-------------------- Amazing ![]() |
|||
|
||||
ksnk |
|
|||
![]() прохожий ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 6855 Регистрация: 13.4.2007 Где: СПб Репутация: 96 Всего: 386 |
MoLeX, это про использование битовых операций? А при чем тут они? Меня больше интересовала реализация "полноформатного" распределения прав без привязки к количеству допустимых операций (в битовом представлении их не более 32
![]() -------------------- Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! ![]() |
|||
|
||||
krundetz |
|
|||
![]() Вечный странник ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1400 Регистрация: 14.6.2007 Где: НН(Сормово) Репутация: 20 Всего: 69 |
ksnk, я делаю так:
Есть список пользователей (в моем случае это администраторы, хотя может быть всем чем угодно) кто получает права. Есть список объектов (в моем случае это методы) на которые выдаются права. Есть связи. Установления связей прав происходит в один запрос, и получение тоже в один. Для того чтобы добавить объект на работу с которым требуются права, есть специальный API которому должен удовлетворять объект. (Чтобы автоматически распознать такой объект и узнать его идентификатор). Так же с пользователями. Ну и соответственно есть механизм работающий с этим API. Это сообщение отредактировал(а) krundetz - 16.12.2011, 14:13 |
|||
|
||||
ksnk |
|
|||
![]() прохожий ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 6855 Регистрация: 13.4.2007 Где: СПб Репутация: 96 Всего: 386 |
krundetz, как-то конкретики не очень много. У меня тоже, вроде как список объектов и список пользователей, с группами и блекджеком. И права получаются одним запросом (ну, это если не пренебрегать кэшированием...) И Апи вроде как есть... Это не про мой механизм, случайно?
![]() Это сообщение отредактировал(а) ksnk - 16.12.2011, 15:43 -------------------- Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! ![]() |
|||
|
||||
krundetz |
|
|||
![]() Вечный странник ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1400 Регистрация: 14.6.2007 Где: НН(Сормово) Репутация: 20 Всего: 69 |
я так понял, что у тебя с конкретикой все в порядке, ты чисто теоретически переживаешь, что чет все слишком просто получилось, хотя phpGACL ажно 3мб в за архивированном виде. Если нужен пример могу накатать в выхи если торжество позволит. Добавлено через 10 минут и 5 секунд MoLeX, статейка конечно интересная, сам ее позавчера изучал, только имеет смысл если у тебя весь механизм уже работает реально
А у тебя так много операций, по моему все сводиться как всегда к CRUD? |
|||
|
||||
![]() ![]() ![]() |
Правила форума "PHP" | |
|
Новичкам:
Важно:
Внимание:
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | PHP: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |