Большинство важных мощных вещей требуют какого-нибудь контроля доступа. Списки контроля доступа это удобный способ управлять разрешениями вашего приложения. Списки контроля доступа или ACL, обрабатывают две основные вещи: вещи которые требуют что-то, и вещи которых требуют. На жаргоне ACL, вещи (чаще всего пользователи), которые требуют использования чего-то называются объектами запроса доступа(access request objects), или AROсами. Вещи, которых требуют в системе (чаще всего действия или данные) называются объектами контроля доступа, или ACOсами. Вообще эти «вещи» называют объектами, поскольку иногда запрашивающие объекты это не люди – иногда вам может понадобится ограничить доступ определенному контроллеру Cake, чтобы он не инициировал код в других частях вашего приложения. АСОсы могут быть чем угодно, что вы будите контролировать, от действий контроллера до веб-сервисов, или же линии с он-лайнового дневника вашей бабушки.
Ну и чтобы использовать все акронимы сразу: ACL это то, что решает когда ARO может получить доступ к ACO.
Теперь, чтобы помочь вам понять это, давайте воспользуемся практическим примером. Представьте на мгновение компьютерную систему, которую будет использовать группа искателей приключений. Лидер группы хочет продвигаться вперед в их задании, соблюдая приличную толику конфиденциальности и безопасности для остальных членов глуппы. AROсы вовлечены так:
Это объекты в системе, которые будут запрашивать вещи (АСОсы) из системы. Кстати вы должны отметить что ACL это *не* система аутентификации пользователей. У вас уже должен быть способ хранить информацию о пользователях и способ индентифицировать пользователей, когда они входят в систему. Когда вы уже знаете кем является пользователь, тогда уже сияет ACL. Ладно – вернемся к нашему приключению.
Дальше Гендальфу нужно сделать исходный список вещей, или АСОсов, с которыми будет работать система. Его список может выглядить так:
Обычно, системы управляются, использованием определенных матриц, которые показывают основные установки пользователей и их прав. Если эта информация хранится в таблице, она может выглядить как следующая, с символом Х – закрытый доступ, или символом О – открытый доступ.
На первый взгляд, кажется что этот вид системы может работать достаточно хорошо. Распределение может быть сделано, чтобы поддержать безопасность (только Фродо может получить доступ к кольцу) и защититься от несчасных случаев (держит хоббитов подальше от соленной свинины). Она кажется достаточно продуктивной и достаточно легкой для чтения, не так ли?
Для маленькой системы вроде этой, возможно матричные настройки и будут работать. Но для растущей системы, или системы с огромным количеством ресурсов (АСОсов) и пользователей (ARCсов), таблица достаточно быстро может стать неуклюжей. Представьте себе попытки получить доступ к сотням военных расположений и попытки управлять ими по одному бойцу, например. Еще один недостаток матриц – вы действительно не можете логически групировать разделы пользователей, или создавать каскадные изменения привилегий в группе, базируясь на этом логическом группировании. Например, наверняка было бы прекрасно автоматически давать доступ хоббитам к элю и свинине, когда битва закончена: Делать это индивидуально каждому пользователю, нудно и очень легко допустить ошибку, в то время как сделать каскадные изменения в привилегиях всем хоббитам было бы легким и быстрым занятием.
ACL чаще всего используется в структуре дерева. Обычно дерево AROсов и дерево АСОсов. Огранизовуя свои объекты в деревья, привилегии по-прежнему могут быть согласованы в форме гранул, в то же время поддерживается хороший захват на большой картине. Будучи мудрым лидером, Гендальф решил использовать ACL в своей новой системе, и организовать свои объекты согласно следующему:
Структрируя нашу группу таким образом, мы можем определить контроль доступа к целому дереву, и применить эти привилегии к любому дочернему объекту. По умолчанию привилегии – доступ закрыт ко всему. Пока вы работаете с деревом, вы устанавливаете привилегии и применяет их. Так что, используя наше ARO дерево, Гендальф может повесить несколько привилегий:
Если мы хотим воспользоваться ACL чтобы узнать разрешен ли Пиппину доступ к элю, мы сначала берем его путь в дереве, это Fellowship->Hobbits->Pippin. Затем смотрим на разные привилегии и используем наиболее относящееся к Элю и Пиппину разрешение.
Дерево также позволяет нам создать лучшие регулировки для более гранулированого контроля – в то же время поддерживая возможность делать более размашистые изменения в группах AROсов:
Вы можете видеть это, поскольку ARO Арагорн поддерживает привилегии как и другие в группе ARO Воины, но вы также можете сделать регулировку и установить дополительные привилегии. Снова, привилеги по умолчанию – ЗАПРЕТИТЬ, и изменяются вниз по дереву привилегиями РАЗРЕШИТЬ. Чтобы проверить может ли Мерри получить доступ к Элю, мы найдем его путь в дереве: Fellowship->Hobbits->Merry и пойдем вниз по дереву, просматривая привилегии связанные с элем:
Первый ACL Cake'а не базировался на файлах INI, хранящихся в директории Cake. В то время как это полезно и стабильно, мы рекомендуем использовать базу данных с ACL, особенно из-за того, что есть возможность создавать новые АСОсы и AROсы на лету. Мы имеем ввиду использование в простых приложениях – и особенно для тех людей, которые по каким-то причинам не используют базу данных.
ARO/ACO привилегии определены в /app/config/acl.ini.php. Иструкции по определению доступа находятся в начале acl.ini.php:
Используя файл INI, вы можете определить пользователей (ARO), группу(ы) к которой они принадлежат, и их личные привилегии. Вы также можете определить группы с их привилегиями. Чтобы узнать как использовать компонент ACL Cake'а, чтобы проверить привилегии используя этот файл INI, взгляните на раздел 11.4.
По умолчанию использование привилегий ACL подразумевает хранение данных в базе данных. База данных ACL, или dbACL состоит из набора основных моделей, и скрипта командной строки, которая поставляется с Cake. Модели используются для взаимодействия Cake с вашей базой данных для хранения и извлечения узлов деревьев ACL. Скрипт командной строки используется, чтобы помочь вам начать и получить возможность взаимодействовать с вашими деревьями.
Для начала, убедитесь, что ваш /app/config/database.php существует и коректно настроен. Для новой установки Cake, самый легкий способ сообщить что все проверено, это войти в установочную директорию, используя браузер. Вверху страницы вы должны увидить сообщения «Файл настройки вашей базы данных существует.» и «Cake может подключиться к базе данных.» если вы все сделали правильно. Посмотрите раздел 4.1, там больше информации по настройке базы данных.
Далее, воспользуйтесь скриптом командой строки, чтобы инициализировать вашу базу данных для хранения информации ACL. Закончить это вам поможет скрипт, находящийся в /cake/scripts/acl.php. Инициализируйте базу данных для ACL выполнением следующей команды (из вашей директории /cake/scripts/)
На этом этапе, вы уже можете проверить базу данных своего проекта и увидеть новые таблицы. Если вам любопытно, как Cake хранит информацию дерева в этих таблицах, просмотрите модифицированные деревья в базе данных. В таблицах асоs и aros храняться узлы для соответсвующих деревьев, а таблица aros_acos используется для связи ваших AROсов с ACOсами, к которым у них есть доступ.
Теперь, вы можете создавать свои ARO и ACO деревья.
Есть два способа сослаться на AROсы/АСОсы. Первый, присваивая им номерованные id, которые обычно являются главными ключами таблицы, к которой принадлежат. Второй, присваивая им строковые псевдонимы. Второй – не очень эксклюзивный.
Создать новый ARO можно методами определенными моделью Cake Aro. Метод create() класса Aro требует три параметра: $link_id, $parent_id и $alias. Этот метод создает новый объект ACL под родительским с id определенным parent_id – или как корневой объект если $parent_id равна нолю. Переменная $link_id позволяет вам связать текущий объект со структурой ACL Cake'а. Параметр $alias позволяет вам направлять ваш объект, используя не целое ID.
Перед тем как мы сможем создать наши АСОсы и AROсы, нам понадобится загрузить эти классы. Самый простой способ сделать это, включить ACL компонент в свой контроллер, использовав масив $components:
var $components = array('Acl');
Когда это сделано, давайте посмотрим как могут выглядить примеры создания этих объектов. Следующий код можно размещать где-нибудь в действии контроллера:
<?
$aro = new Aro();
// Сначала создадим несколько AROсов.
// Эти объекты не будут дочерними.
$aro->create( 1, null, 'Bob Marley' );
$aro->create( 2, null, 'Jimi Hendrix');
$aro->create( 3, null, 'George Washington');
$aro->create( 4, null, 'Abraham Lincoln');
// Теперь мы можем создать группы, чтобы организовать этих пользователей:
// Заметьте, что номера ID этих объектов ноли, потому что
// они никогда не будут связывать пользователей в вашей системе
$aro->create(0, null, 'Presidents');
$aro->create(0, null, 'Artists');
//Теперь прикрепим AROсы к соответствующим группам:
$aro->setParent('Presidents', 'George Washington');
$aro->setParent('Presidents', 'Abraham Lincoln');
$aro->setParent('Artists', 'Jimi Hendrix');
$aro->setParent('Artists', 'Bob Marley');
//Вкратце, вот как создать ARO:
$aro = new Aro();
$aro->create($user_id, $parent_id, $alias);
?>
Вы также можете создать AROсы, используя скрипт командной строки, вводя $acl.php create aro <link_id> <parent_id> <alias>.
Создание АСО происходит в той же манере:
<?
$aco = new Aco();
//Создаем какие-то АСОсы:
$aco->create(1, null, 'Electric Guitar');
$aco->create(2, null, 'United States Army');
$aco->create(3, null, 'Fans');
// Я предполагаю мы можем создать группы для этих
// АСОсов используя setParent(), но мы пропустим это
// в этом примере.
//Итак, чтобы создать АСО:
$aco = new Aco();
$aco->create($id, $parent, $alias);
?>
Соответствующая команда для командной строки: $acl.php create aco <link_id> <parent_id> <alias>.
После того, как мы создали АСОсы и AROсы, мы наконец-то можем назначить привилегии между двумя группами. Это делается центральным ACL компонентом Cake'а. Давайте продолжим с нашим примером:
<?
// Сначала, в контроллере, нам понадобиться доступ к
// ACL компоненту Cake'а:
class SomethingsController extends AppController
{
// Может быть, вместо этого, вы захотите поместить это в AppController,
// но здесь он также отлично работает.
var $components = array('Acl');
// Запомните: ACL всегда будет запрещать то,
// информации на что у него нет. Если любые
// проверки были сделаны на всем, это будет
// запрещено. Давайте дадим доступ ARO к АСО.
function someAction()
{
//РАЗРЕШИТЬ
// Вот как вы можете дать ARO полный доступ к АСО
$this->Acl->allow('Jimi Hendrix', 'Electric Guitar');
$this->Acl->allow('Bob Marley', 'Electric Guitar');
// Мы также можем назначать привилегии группам, помните?
$this->Acl->Allow('Presidents', 'United States Army');
// Метод allow() имеет третий параметр, $action.
// Вы можете определять частичный доступ, используя этот параметр.
// $action может быть равен create, read, update или delete.
// Если не определенно никакого действия, это воспринимается как полный доступ.
// Смотрите, но не трогайте, джентльмен:
$this->Acl->allow('George Washington', 'Electric Guitar', 'read');
$this->Acl->allow('Abraham Lincoln', 'Electric Guitar', 'read');
//ЗАПРЕТИТЬ
//Запрет работает в той же манере:
//Когда его срок истек...
$this->Acl->deny('Abraham Lincoln', 'United States Army');
}
}
?>
Частичный контроллер не особо полезен, но он в основном нужен был, чтобы показать вам как происходит процесс. Ипользование Acl компонента в соединении с вашим контроллером управления будет лучшим вариантом. Когда пользователь был создан в системе, его ARO может быть создан и помещен в подходящее место в дереве, и можно назначать привилегии, чтобы определить ACO или группы АСО.
Привилегии также можно назначить из командной строки. Синтаксис такой же как у функции модели, и можно его отобразить использовав $php acl.php help.
Проверка привилегий этой самое простое в использовании ACL Cake'а: она состоит из использования отдельного метода из Acl компонента: check(). Хороший способ для использования ACL в вашем приложении – это поместить действие в ваш App Controller?, который выполняет ACL проверки. Когда действие помещено туда, вы можете получить доступ к Acl компоненту и выполнять проверку привилегий на ширину всего приложения. Вот пример испльзования:
<?
class AppController extends Controller
{
// Получаем наш компонент
var $components = array('Acl');
function checkAccess($aco)
{
// Проверка доступа используя компонент:
$access = $this->Acl->check($this->Session->read('user_alias'), $aco, $action = "*");
//доступ закрыт
if ($access === false)
{
echo "access denied";
exit;
}
//доступ разрешен
else
{
echo "access allowed";
exit;
}
}
}
?>
Делая Acl компонент доступным в App Controller?, он будет доступен из любого контроллера в вашем приложении.
<?
//Вот основной формат:
$this->Acl->Check($aro, $aco, $action = '*');
?>