Приветствую, хабра-сообщество!
У каждого проекта (веб-проекта) возникают вопросы по организации прав доступа. В данной области есть определенные готовые инструменты для различных фреймворков Zend, Symfony, Yii и т. д. Вероятно кто-то с чем-то сталкивался и в целом представляет себе, что это такое. Для тех же кто не сталкивался — советую открыть документацию любого из этих фреймворков и ознакомится. В частности автор поста очень плотно работал с Zend_Acl. Но относительно недавно решил изучить вопрос ACL в области C++
Итак, с чего все началось...
Началось все весьма просто, есть самописный проект с неплохой нагрузкой (по этическим соображениям название его не называется, самописный он по историческим причинам, 200К уников). Проект, как в большинстве случаев «диктует традиция» написан на php. Организация списков доступа в нем, как таковая отсутствует — есть банальные условные операторы в случае какой «роли», что делать. Данные костыльные решения в принципе работают, но крайне не устраивают. Вооружившись поиском и здравым смыслом было принято решение создать не большую, легкую c++ утилиту, которой мне бы и хотелось поделится с сообществом.
Конфигурация прав доступа
Проанализировав детальнее зенд и идеологию списков доступа было понятно, что требования к утилите весьма простые, — она должна получить список прав и в зависимости от ситуации ответить разрешен ли доступ к тому, или другому ресурсу, кроме того, т. к. данный конфигурационный файл могут править системные администраторы — им должно быть легко ориентироваться что к чему. Из этих соображений был сделан выбор в сторону привычного конфигурационного ini файла. Пример:
[guest]
view:news
view:comments
Где [guest] — это роль пользователя, а view:news и view:comments — соответствующие ресурсы. Многие могут заинтересоваться, почему, допустим ресурс называется не comments:view, а наоборот view:comments — ответ прост, если условно поделить ресурсы в соответствии с CRUD бд, вы поймете, что не так много можно придумать вариантов, соответственно просматривая роли визуально сразу можно разделить, кто что смотрит, кто обновляет и т. д. Кроме того в таком формате становится возможным сделать так:
[guest]
view:*
Что в свою очередь означает — гостям разрешено все смотреть.
Просто, не правда ли?
Внимательный читатель, очевидно, уже успел заметить, что в названии ресурса присутствует символ двоеточие. Это условный обязательный разделитель с помощью которого можно делать такие штуки:
[moderator]
edit:*:comments
# или
edit:news:comments
edit:wall:comments
Утилита не навязывает группировку ресурсов и вы можете группировать, как считаете нужным и как больше подходит вашему проекту. Но наличия двоеточия между подгруппами позволяет более логично разделять составные части ресурса.
Простое разрешение неинтересно, очевидно мы можем и запрещать доступ к отдельным ресурсам:
[user]
view:news:28 = deny
Данным правилом мы запретили пользователю просматривать новость с ID 28
Описывать правила для каждой отдельной роли весьма утомительно, поэтому существует механизм наследования:
[user : guest]
В данном случае роль user, кроме своих правил, будет также содержать в себе правила от роли guest
Дополнительной фишкой на мой взгляд является возможность в конфигурации описать случай, когда пользователь может править свои комментарии. То есть только те, непосредственно которые он создал. Для этого используется символ ^
Например:
[user]
edit:comment:^
Думаю, теперь понятнее выглядит, почему ж таки принудительно используется двоеточие на разбиение по подгруппам, ибо в данном случае вместо ^ будет подставляться ID комментария.
Как это работает
Как говорилось выше это утилита. Соответственно после её успешной компиляции можно выполнить в консоли:
./x-acl --config x-acl.conf --group guest --resource view:news
Спрашиваем есть ли доступ у гостевого пользователя к ресурсу view:news
./x-acl --config x-acl.conf --group user --resource edit:comment:28
--user-id 4 --owner-id 4
Спрашиваем есть ли доступ у роли user к ресурсу edit:comment:28, если кто забыл мы поставили правило edit:comment:^, — в данном случае стоит символ ^ поэтому идет проверка аргументов user-id и owner-id на равенство и если они равны (а они равны в данном примере) — доступ будет разрешен.
Где можно скачать и поиграться
github.com/AlexeyParhomenko/x-acl
Список подозреваемых вопросов :)
— Зачем изобретать свой велосипед, если есть готовые инструменты?
Автор знаком с некоторыми. Создать новый инструмент побудило:
1. Сделать acl более гибче под наши нужды;
2. Поднять профит по потреблению памяти, т. к. в данном случае в отличии от php нет создания громоздких Zval структур;
3. Поднять профит в скорости. Пока мы тестируем, но если окажется напряжным парсить конфиг каждый раз, — мы сможем перейти на сокетное решение;
— Планируется ли дальнейшая поддержка и фикс багов?
Естественно.
— Для каких ОС работает?
На наших серверах используется дебиан, как и у автора в виде рабочей среды, поэтому точно скажу, что на дебиане работает отлично. На других *nix дистрибутивах должно работать также стабильно, ибо ниче не родного не используется. Ну разве что, кому религия не позволяет использовать boost и то, он только для парсинга коммандной строки :)
Очень приветствуются комментарии, т. к. хотелось бы понять насколько полезным может быть в дальнейшем данный инструмент. Либо, если я плохо искал и уже описанный функционал имеется — отправьте в гугл!
Замеченные ошибки/неточности в тексте или исходном коде буду рад выслушать в личке, либо, возможно, какие-то дальнейшие пожелания.
Автор: AlexeyParhomenko