Контроль мелкозернистого доступа

Я знаком с целым рядом способов аутентификации пользователей для веб-приложения администрирования, которое мы разрабатываем, и даже различных методов, чтобы следить за авторизацией …

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

  1. Пользователи принадлежат к «ролям» или «группам», таким как «продавец», «планирование» и т. Д.
  2. В системе меню администратора отображаются только «страницы», которые имеют функции, относящиеся к роли пользователей.
  3. Специфические функции на этих страницах имеют ограничения – например, на странице «нового бронирования» пользователи «продавца» могут выпустить бронирование «только в будущем», а на странице «Редакционные заказы» можно редактировать заказы через неделю ». Тем не менее, пользователям «планирования» может быть позволено ретроспективно бронировать «до одной недели назад» и редактировать заказы, сделанные сами по себе для «любого периода времени», но заказы, сделанные другими, только «до завтра» …

Я знаю, что могу реализовать базовую систему на основе ролей, чтобы удовлетворить №1. У меня есть ощущение, что я должен разбить все приложение на куски кода, каждый со своим отношением objectID-permissionID, чтобы я мог сканировать базу данных разрешений чтобы увидеть, какие объекты доступны – это поможет мне без 2.

Любые идеи о том, как я могу, например, создать элемент управления формой, который для пользователей «продаж» отображает дату в будущем (но отображает даты до «одной недели назад» для планирования пользователей), то каким-то образом сопряжение с линией в POST, который проверяет, действительно ли дата находится в ожидаемом диапазоне?

Я играл с идеей, что я должен сохранить каждый фрагмент кода в базе данных, а затем иметь таблицу объектов, которая динамически создает код в соответствии с таблицей разрешений, так что единственным «файлом» на сервере является файл подключения db!

Любые идеи приветствуются … (даже если ваш фон не php / MySQL)


Более подробная информация о проблеме из презентации CUSEC Зеда Шоу рассказывает о том, почему «ACL мертв» – http://vimeo.com/2723800

    Предупреждение, много Zend Framework впереди!

    Вы можете легко справиться с 1. и 2. с Zend_Acl и Zend_Navigation .

    Для номера 3 вам нужно будет запросить объект ACL в вашей модели и сделать много вещей вручную. Вы также можете использовать Zend Framework для форм и включать в себя определенные элементы проверки элементов формы в зависимости от разрешения роли пользователей.

    РЕДАКТИРОВАТЬ:

    Если вам не нравится идти по маршруту ZF, вы можете хотя бы взглянуть на то, как ACL обрабатывается в ZF.

    Если вы хотите создать реальный мелкомасштабный контроль доступа (FGAC), просто проверьте мою статью на эту тему для MySQL:

    MySQL 5.0 Fine-Grained Access Control (FGAC)

    В принципе, вы не хотите, чтобы ваш бизнес-код зависел от реализации FGAC, вы не хотите смешивать код FGAC в разделе предложений select операторов ваших бизнес-правил. В этой статье представлены решения, позволяющие избежать загромождения операторов SQL.

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

     // Check database for existence of this $user against this $object. function get_permission($user, $object){ // Query goes here... if( ... ){ return $permission; } else { return FALSE; } } 

    Вышеупомянутая функция будет запрашивать базу данных и выводить что-то вроде этого:

     // Result of role-object query. role_ID object_ID permission ------- --------- ---------- salesperson new_booking_date 'min' => 'now', 'max' => '+1 year' planning new_booking_date 'min' => '-1 week', 'max' => '+1 year' salesperson edit_booking_date 'this_user_min' => 'now', 'this_user_max' => '+1 week', 'other_user_min' => 'now', 'other_user_max' => '+1 week' planning edit_booking_date 'this_user_min' => '-1 week', 'this_user_max' => '+1 year', 'other_user_min' => '-1 week', 'other_user_max' => '+1 week' 

    Следующий код на странице, содержащей ввод формы:

     // Draw form control with javascript date validation... $this_permission = get_permission($this_user, 'new_booking_date'); if($this_permission){ $html->datepicker('min' => $this_permission['min'], 'max' => $this_permission['max']); } 

    После того, как бронирование было сделано, другая страница позволяет нам отредактировать это поле:

     // Verify POST data... $this_permission = get_permission($this_user, 'edit_booking_date'); if($this_permission){ if($this_user == $author_user && $_POST['date'] >= strtotime($this_permission['this_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['this_user_max'], $date_ref)){ // Update database... } elseif($_POST['date'] >= strtotime($this_permission['other_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['other_user_max'], $date_ref)){ // Update database... } } 

    Я нахожусь на жестком треке?

    Я разработал библиотеку под названием PHP-Bouncer, которая, как я думаю, будет очень хорошо соответствовать вашим потребностям. В настоящее время он поддерживает полностью управляемый доступ, который позволит вам использовать один вызов на каждой странице (я рекомендую использовать курсор, конечно), и автоматически перенаправлять людей, если у них нет доступа к странице, а также автоматический поиск ролей из базы данных (если вы реализуете роли в БД, используя встроенный скрипт настройки таблицы MySQL). Синтаксис довольно прост.

    Вы создаете вышибалу:

     $bouncer = new Bouncer(); 

    Добавьте свои роли (вручную):

     // Add a role Name, Array of pages role provides $bouncer->addRole("Public", array("index.php", "about.php", "fail.php")); // Add a role Name, Array of pages role provides $bouncer->addRole("Registered User", array("myaccount.php", "editaccount.php", "viewusers.php")); // Add a role Name, Array of pages role provides List of pages that are overridden by other pages $bouncer->addRole("Admin", array("stats.php", "manageusers.php"), array("viewusers.php" => "manageusers.php")); 

    или из базы данных:

     // conf_* values are set in a config file, or you can pass them in explicitly $bouncer->readRolesFromDatabase(conf_hostname, conf_username, conf_password, conf_schema, "mysql"); 

    Добавьте пользователя и дайте им некоторые роли (Примечание. Существует класс BouncerUser, который может расширить ваш класс пользователя, он предоставляет все необходимые функции роли!):

     $user->addRole("Logged In"); // This Role doesn't exist in the bouncer, but we can set it anyways if we feel like setting another flag on the user's account. This can be useful for displaying content in a page only if a user has a secondary role. $user->addRole("Public"); $user->addRole("Registered User"); 

    Затем пусть Bouncer управляет доступом к вашим файлам:

     $bouncer->manageAccess($user->getRoles(), substr($_SERVER["PHP_SELF"], 1), "fail.php"); // Any time the user tries to go to a page they don't have access to, they will get to // fail.php. Any time they try to go to a page that is overridden for them, they will // get to the overriding page. 

    Если вы хотите показывать контент на странице только в том случае, если у пользователя есть разрешение на просмотр, просто оберните его:

     if($user->hasRole("Registered User")){ echo "The content"; } 

    Я думаю, что для проблемы, которую вы описали, это было бы отличным решением!