Система разделения прав доступа в веб-приложении — часть 1, теория
В данный момент моя небольшая команда из двух человек, занята разработкой CMS. Я представляю примерно сколько их уже существует, но хочется внести свою лепту.
Ниже я хочу поделиться мыслями о системе разделения прав доступа в CMS. Кажется она получается весьма оригинальной и интересной.
Думая о реализации, я поставил следующие цели:
В итоге, я пришел к выводу, что самый подходящий аналог — мандатная система доступа к файлам в unix-е. Та самая, которая 777. :) Естественно с поправками на веб-ориентацию — вместо каталогов у нас будут категории, вместо файлов — разные веб-объекты, и т.д. Обо всем ниже.
В самом общем приближении — система будет хранить таблицу, в которой будут содержаться идентификаторы всех объектов, и права доступа к ним.
Технические проблемы (к примеру разнотипность ключей объектов, использование системы на усмотрение разработчика), а также оптимизацию — обсудим позже. Пока идем по стратегии.
У каждого объекта будет владелец-пользователь, владелец-группа и число, которое будет описывать, что с этим объектом делать. В unix-системах, такое число содержит 3 цифры для описания прав
У нас будет больше на одну цифру:
Теперь о более интересном. В операционной системе, как правило, хватает контроля всего над тремя операциями — чтение, запись, исполнение. Плюс пара дополнительных флагов.
У нас ситуация сложнее — может быть много других операций, которые надо контролировать. Описание прав на чтение/запись/исполнение не хватит. К примеру, на сайте с объявлениями, пользователь может изменять свое объявление, но не может загружать в него фотографии. Эта возможность открывается после оплаты. Или возможность скачать приложенные файлы — ее тоже надо контролировать.
Получается, что в отличии, от ОС, где всего три операции — у нас количество этих операций — потенциально неограниченно. Их много, и кроме того, они могут меняться от приложения к приложению. И все же этому есть красивое решение.
Каждую цифру можно разбить на верхние байты — самые стандартные операции для всех объектов, а также какая-то часть зарезервированная на будущее. И нижние байты, которые сможет определять само приложение. Если ему конечно не хватит стандартных.
Необходимости во флагах как в unix-е я не вижу, т.к. флаги посути лишь добавляют разрядность, когда надо. У нас флаги будут в самой маске доступа (надеюсь этот термин подходит).
В итоге, допустим для статьи, мы получим маску доступа, которая будет выглядеть примерно так:

Что эта она означает и кому, что разрешено — думаю понятно из рисунка.
В каждой группе — две подгруппы. Первая подгруппа из 4х бит — зарезервированные для наиболее стандартных. Вторая подгруппа — определяется отдельно каждым модулем. У нас, там к примеру, будет описана возможность размещения файлов.
В базе данных эта маска будет записана как число 3 633 352 832.
В примере разрядность — 32 бита — тип данных INT. Это для примера. В реальной жизни я наверное воспользуюсь BIGINT размером в 64 бита. Соответственно все группы и подгруппы будет больше в 2 раза.
Как я предполагаю использование — при попытке доступа к объекту — модуль должен будет запросить права доступа на объект. Система вытащит это число из базы, разберет по битам и вернет модулю в каком-то красивом виде. Допустим в виде удобно обрабатываемого массива. Дальше модулю следует поступить как полагается.
Количество записей в таблице прав будет расти прямолинейно от количества объектов в системе. В принципе это терпимо, но можно сделать еще красивее — выделить стандартные для модулей маски. И в таблицу записывать объекты только с нестандартными правами — количество записей сократится на порядок.
Нельзя принудить разработчиков пользоваться этой системой. Но, при ее использовании они получат следующие плюсы:
все сделано — бери и пользуйся;
меньше шансов допустить ошибку в коде;
у пользователя на все модули и их объекты будет один универсальный и привычный интерфейс.
Использование этой системы, кстати, не исключает и другие способы контроля доступа. Такие, как списки доступа.
Если статья понравится сообществу — появится статья Система разделения прав доступа в веб-приложении — практика. :)
P.S. В теории безопасности не очень силен — поправьте, если ошибся где в терминах.
P.P.S. Подобную систему в вебе не встречал, хотя возможно где-то далеко, а может и близко — она есть. Если так — киньте ссылку.
P.P.P.S. Первый пост на хабр — возможны «детские» ошибки, укажите на них — быстро поправлю.
UPDATE: Теперь пост в блоге о CMS и на главной странице хабра. Спасибо, хабралюди! :)
Отдельное спасибо mexxv за карму для перемещения поста и metamorph за ссылку на хорошую статью идейно крайне близкую ко мне.
Порадовался в своем блоге попаданию на главную хабра. Инфу там не публикую пока, боюсь он не выдержит хабра-эффекта — надо готовить заранее. :)
А теперь по делу. Комменты помогли понять основную проблему предложенной системы — гибкости все же недостаточно. Надо больше. Может быть используя гибрид с ACL, может быть за счет больших возможностей наследования. Постараюсь все обмысленные итоге подвести к завтрашнему дню.
UPDATE: mephius говорит что предложенная мной идея с приправой из ALC работает на мега-крутом сайте.
Кстати, я заработал первый хабраинвайт. :)))
Ниже я хочу поделиться мыслями о системе разделения прав доступа в CMS. Кажется она получается весьма оригинальной и интересной.
Думая о реализации, я поставил следующие цели:
- единый API для всех модулей;
- просто и удобно для разработчиков;
- просто и удобно для пользователей;
- приемлемая скорость и объем данных;
- гибкость возможностей.
В итоге, я пришел к выводу, что самый подходящий аналог — мандатная система доступа к файлам в unix-е. Та самая, которая 777. :) Естественно с поправками на веб-ориентацию — вместо каталогов у нас будут категории, вместо файлов — разные веб-объекты, и т.д. Обо всем ниже.
В самом общем приближении — система будет хранить таблицу, в которой будут содержаться идентификаторы всех объектов, и права доступа к ним.
Технические проблемы (к примеру разнотипность ключей объектов, использование системы на усмотрение разработчика), а также оптимизацию — обсудим позже. Пока идем по стратегии.
У каждого объекта будет владелец-пользователь, владелец-группа и число, которое будет описывать, что с этим объектом делать. В unix-системах, такое число содержит 3 цифры для описания прав
- владельца — пользователя;
- владельца — группы;
- остальных пользователей.
У нас будет больше на одну цифру:
- владельца — пользователя;
- владельца — группы;
- остальные зарегистрированные пользователи;
- остальные незарегистрированные пользователи.
Теперь о более интересном. В операционной системе, как правило, хватает контроля всего над тремя операциями — чтение, запись, исполнение. Плюс пара дополнительных флагов.
У нас ситуация сложнее — может быть много других операций, которые надо контролировать. Описание прав на чтение/запись/исполнение не хватит. К примеру, на сайте с объявлениями, пользователь может изменять свое объявление, но не может загружать в него фотографии. Эта возможность открывается после оплаты. Или возможность скачать приложенные файлы — ее тоже надо контролировать.
Получается, что в отличии, от ОС, где всего три операции — у нас количество этих операций — потенциально неограниченно. Их много, и кроме того, они могут меняться от приложения к приложению. И все же этому есть красивое решение.
Каждую цифру можно разбить на верхние байты — самые стандартные операции для всех объектов, а также какая-то часть зарезервированная на будущее. И нижние байты, которые сможет определять само приложение. Если ему конечно не хватит стандартных.
Необходимости во флагах как в unix-е я не вижу, т.к. флаги посути лишь добавляют разрядность, когда надо. У нас флаги будут в самой маске доступа (надеюсь этот термин подходит).
В итоге, допустим для статьи, мы получим маску доступа, которая будет выглядеть примерно так:

Что эта она означает и кому, что разрешено — думаю понятно из рисунка.
В каждой группе — две подгруппы. Первая подгруппа из 4х бит — зарезервированные для наиболее стандартных. Вторая подгруппа — определяется отдельно каждым модулем. У нас, там к примеру, будет описана возможность размещения файлов.
В базе данных эта маска будет записана как число 3 633 352 832.
В примере разрядность — 32 бита — тип данных INT. Это для примера. В реальной жизни я наверное воспользуюсь BIGINT размером в 64 бита. Соответственно все группы и подгруппы будет больше в 2 раза.
Как я предполагаю использование — при попытке доступа к объекту — модуль должен будет запросить права доступа на объект. Система вытащит это число из базы, разберет по битам и вернет модулю в каком-то красивом виде. Допустим в виде удобно обрабатываемого массива. Дальше модулю следует поступить как полагается.
Количество записей в таблице прав будет расти прямолинейно от количества объектов в системе. В принципе это терпимо, но можно сделать еще красивее — выделить стандартные для модулей маски. И в таблицу записывать объекты только с нестандартными правами — количество записей сократится на порядок.
Нельзя принудить разработчиков пользоваться этой системой. Но, при ее использовании они получат следующие плюсы:
все сделано — бери и пользуйся;
меньше шансов допустить ошибку в коде;
у пользователя на все модули и их объекты будет один универсальный и привычный интерфейс.
Использование этой системы, кстати, не исключает и другие способы контроля доступа. Такие, как списки доступа.
Если статья понравится сообществу — появится статья Система разделения прав доступа в веб-приложении — практика. :)
P.S. В теории безопасности не очень силен — поправьте, если ошибся где в терминах.
P.P.S. Подобную систему в вебе не встречал, хотя возможно где-то далеко, а может и близко — она есть. Если так — киньте ссылку.
P.P.P.S. Первый пост на хабр — возможны «детские» ошибки, укажите на них — быстро поправлю.
UPDATE: Теперь пост в блоге о CMS и на главной странице хабра. Спасибо, хабралюди! :)
Отдельное спасибо mexxv за карму для перемещения поста и metamorph за ссылку на хорошую статью идейно крайне близкую ко мне.
Порадовался в своем блоге попаданию на главную хабра. Инфу там не публикую пока, боюсь он не выдержит хабра-эффекта — надо готовить заранее. :)
А теперь по делу. Комменты помогли понять основную проблему предложенной системы — гибкости все же недостаточно. Надо больше. Может быть используя гибрид с ACL, может быть за счет больших возможностей наследования. Постараюсь все обмысленные итоге подвести к завтрашнему дню.
UPDATE: mephius говорит что предложенная мной идея с приправой из ALC работает на мега-крутом сайте.
Кстати, я заработал первый хабраинвайт. :)))



комментарии (228)