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