Система контроля доступа PHP
-
04-07-2019 - |
Вопрос
Я являюсь частью команды, создающей веб-приложение с использованием PHP и MySQL.В приложении будет несколько пользователей с разными ролями.Приложение также будет использоваться географически распределенным образом.Соответственно, нам необходимо создать систему контроля доступа, которая работает на следующих двух уровнях:
- Управляет разрешениями пользователя для определенных php-страниц, т. е.предоставляет или запрещает доступ к определенным страницам (или элементам пользовательского интерфейса) в зависимости от роли пользователя.Например:пользователю может быть разрешен доступ к странице "Учащиеся", но не к странице "Учителя".
- Управляет разрешениями пользователя для определенных записей базы данных, т. е.изменяет запросы к базе данных таким образом, чтобы отображались только определенные записи.Например, для пользователя на уровне города должны отображаться только те записи, которые относятся к конкретному городу пользователя, в то время как для пользователя на национальном уровне должны отображаться записи для ВСЕХ ГОРОДОВ страны.
Мне нужна помощь в разработке системы, которая может обрабатывать оба этих типа контроля доступа.Точка нет.1 кажется достаточно простым.Однако я совершенно не понимаю, как выполнить пункт № 2 без жесткого кодирования информации в SQL-запросах.
Будем признательны за любую помощь.
Заранее спасибо
Винаяк
Решение
Я был в подобной ситуации несколько месяцев назад.Я обнаружил, что такие инструменты, как Zend_Acl, отлично работают, если вы просто проверяете уровень доступа к одному элементу (или к достаточно небольшому их количеству).Это не удается, когда вам нужно получить огромный список элементов, к которым пользователю разрешен доступ.Я создал собственное решение этой проблемы, используя Бизнес-делегат шаблон.BD предоставляет бизнес-логику, которая может быть применена в определенном контексте.В этом сценарии была доставлена логика SQL, которая использовалась в качестве условия фильтрации в подвыборке.Смотрите следующие диаграммы:
(источник: epsi.pl)
И диаграмма последовательности, иллюстрирующая порядок вызовов:
(источник: epsi.pl)
Я написал в блоге об этом решении, к сожалению, все это на польском языке, но вам могут пригодиться фрагменты кода и диаграммы.Что я могу сказать, реализация не из легких, но с точки зрения производительности она является рекордсменом по сравнению с итеративной проверкой доступа к каждому элементу в списке.Более того, описанная выше инфраструктура обрабатывает не только один тип элементов в списке.Он может использоваться при доступе к различным спискам, будь то список городов, стран, продуктов или документов, при условии, что элементы списка реализуют IAuthorizable
интерфейс.
Другие советы
Мне кажется, что вам нужно вот это:(Я буду использовать пример страны / штата / города)
- Список всех стран.У каждой "страны" есть идентификатор.
- Список всех государств внутри стран.Каждое состояние привязано к идентификатору страны, но также имеет свой собственный уникальный идентификатор.
- Список всех городов.Каждый город привязан либо к штату, либо непосредственно к стране, и имеет флаг, указывающий, к какой именно.
Для пользователя из города, очевидно, следует искать и отображать только те записи, относящиеся к городу, которые соответствуют его идентификатору.Однако для уровня штата или нации выполните поиск по всем записям, относящимся к каждому городу, идентификатор которого соответствует этой стране (или штату, или что там у вас есть).
Таким образом, по сути, каждая подгруппа зависит от группы над ней, и хотя я неправильно помню, я полагаю, что вы можете использовать вложенные запросы, чтобы выполнить трюк оттуда.
Если вы не знаете, как это сделать, я бы использовал php-фреймворк, такой как Zend Framework, CakePHP или Symphony.Они проделали за вас тяжелую работу и уже внедрили некоторую схему контроля доступа.
У меня есть аналогичное решение для сборки, и пока я решил использовать спецификации и роли, так что фактически к одной роли были бы прикреплены некоторые спецификации привилегий.Если все они удовлетворены, разрешение предоставляется, в противном случае - он возвращается к доступу к ресурсу по умолчанию.
Я искал кого-нибудь, кто уже внедрил это решение, но, похоже, никто этого не сделал.Будем надеяться, что это не будет провалом :)