Мелкозернистый контроль доступа


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

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

  1. Пользователи принадлежат к "ролям" или "группам", таким как "продавец", "планирование" и т.д.
  2. Система меню администратора показывает только "страницы", которые имеют функции, относящиеся к роли(ролям) пользователей
  3. Специальные функции на этих страницах имеют ограничения - например, на странице "новое бронирование" пользователи "продавец" могут оформить бронирование "только в будущем", а на странице "редактировать заказы" могут редактировать заказы "через неделю". Тем не менее, пользователям "планирования" может быть разрешено ретроспективно бронировать "до одной недели назад" и редактировать заказы, сделанные ими самими на "любой период времени", но заказы, сделанные другими, только "до завтра"...

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

Любые идеи о том, как я мог бы создать, например, элемент управления формой, который для пользователей "продаж" отображает только дату в будущем (но отображает даты до "одного неделю назад" для пользователей планирования), а затем каким-то образом сопоставить это со строкой в анализаторе СООБЩЕНИЙ, которая проверяет, действительно ли дата находится в ожидаемом диапазоне?

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

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


Еще немного понимания проблемы из презентации CUSEC Зеда Шоу, рассказывающего о том, почему "ACL мертв" - http://vimeo.com/2723800

Author: Bill the Lizard, 2009-10-05

4 answers

Внимание, впереди много фреймворков Zend!

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

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

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

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

 4
Author: Goran Jurić, 2009-10-04 22:58:08

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

MySQL 5.0 Мелкозернистый контроль доступа (FGAC)

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

 2
Author: Jérôme Radix, 2010-08-24 12:14:07

В попытке внедрить "родной" подход, а не копилку, поддерживающую структуру, я играл со следующим. Кто-нибудь оценил бы такой подход? Предвидите ли вы какие-либо подводные камни?

// 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...
    }
}

Нахожусь ли я на трек rigt?

 1
Author: boatingcow, 2009-10-05 13:39:34

Я разработал библиотеку под названием PHP-Bouncer, которая, я думаю, очень хорошо удовлетворит ваши потребности. В настоящее время он поддерживает полностью управляемый доступ, который позволит вам использовать один вызов на каждой странице (я, конечно, рекомендую использовать include) и автоматически перенаправлять людей, если у них нет доступа к странице, а также автоматическое извлечение ролей из базы данных (если вы реализуете роли в БД с помощью включенного сценария настройки таблицы 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->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";
}

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

 0
Author: Brendon Dugan, 2012-07-28 14:14:33