Я пытаюсь создать гибкую инфраструктуру ACL в Java для моего приложения.
Многие платформы ACL построены на белом списке правил, где правило имеет форму владельца: действие: ресурс . Например,
- «ДЖОН МОЖЕТ ПОСМОТРЕТЬ ресурс FOOBAR-1»
- «МЭРИ МОЖЕТ ПРОСМОТРЕТЬ ресурс FOOBAR-1»
- "МЭРИ МОЖЕТ РЕДАКТИРОВАТЬ ресурс FOOBAR-1"
Это привлекательно, потому что правила могут быть легко сериализованы / сохранены в базе данных. Но у моего приложения сложная бизнес-логика. Например,
- «Все пользователи в отделе 1 со стажем более 5 лет могут просматривать ресурс FOOBAR-1, иначе не авторизован»
- «Все пользователи в отделе 2, если дата после 15.03.2016, могут ПРОСМОТРЕТЬ ресурс FOOBAR-2, иначе не авторизованы»
На первый взгляд, было бы кошмаром разработать схему базы данных, которая могла бы обрабатывать бесконечно сложные правила, подобные этим. Поэтому мне кажется, что мне нужно «запечь» их в скомпилированном приложении, оценить их для каждого пользователя, а затем создать в результате оценки правила для ресурса owner: action: resource . Я хочу избежать запекания логики в скомпилированном приложении.
Итак, я думал о представлении правила в форме предиката : действия: ресурса , где предикат является логическим выражением, которое определяет, разрешен ли пользователь. Предикатом будет строка выражения JavaScript, которая может быть оценена движком Java Rhino. Например,
return user.getDept() == 1 && user.seniority > 5;
При этом предикаты могут быть легко сохранены в базе данных.
Это умно ? Это небрежно ? Это бесполезно ? Это чрезмерно спроектировано ? Является ли это безопасным (по-видимому, Java может изолировать движок Rhino).
источник
Ответы:
Встраивание динамических данных в интерпретатор языка вашей реализации, как правило, является плохой идеей, поскольку это увеличивает вероятность повреждения данных в потенциальную возможность захвата вредоносных приложений. Другими словами, вы выходите из своего пути к создать в инъекции кода уязвимости.
Ваша проблема может быть лучше решена с помощью механизма правил или, возможно, доменно-ориентированного языка (DSL) . Посмотрите на эти концепции, нет необходимости изобретать велосипед.
источник
==
вместо этого===
в своем примере. Вы действительно хотите обеспечить полноту по Тьюрингу, когда все правила, вероятно, должны всегда заканчиваться? Вместо того чтобы прыгать через обручи, чтобы убедиться, что все взаимодействия между Java и JavaScript являются кошерными, почему бы вам просто не написать простой парсер и интерпретатор, как предложил Килиан? Это будет гораздо проще адаптировать к вашим потребностям и безопасности. Используйте ANTLR или что-то еще.while (true) ;
Я сделал это, и я рекомендую вам не делать этого.
Я написал всю бизнес-логику на Lua и сохранил этот сценарий Lua в базе данных. Когда мое приложение запускалось, оно загружало и выполняло скрипт. Таким образом, я мог бы обновить бизнес-логику своего приложения, не распространяя новый двоичный файл.
Я неизменно обнаруживал, что мне всегда нужно обновлять бинарный файл при внесении изменений. Некоторые изменения были в скрипте Lua, но у меня всегда был список изменений, которые нужно было сделать, и поэтому мне почти всегда приходилось вносить некоторые изменения в двоичный файл и некоторые изменения в скрипте Lua. Мое воображение, что я мог бы избегать распространения бинарных файлов все время, просто не удавалось.
То, что я нашел намного более полезным, состояло в том, чтобы облегчить распределение двоичных файлов. Мое приложение автоматически проверяет наличие обновлений при запуске, загружает и устанавливает любое обновление. Таким образом, мои пользователи всегда используют последние двоичные файлы, которые я загрузил. Почти нет разницы между изменением двоичного файла и изменением сценариев. Если бы я сделал это снова, я бы приложил еще больше усилий, чтобы сделать обновление без проблем.
источник
Я не хотел бы, чтобы база данных содержала код. Но вы можете сделать что-то подобное, если база данных будет содержать имена функций, а затем использовать отражение для их вызова. Когда вы добавляете новое условие, вы должны добавить его в свой код и базу данных, но вы можете комбинировать условия и параметры, которые передаются им, для создания довольно сложных оценок.
Другими словами, если у вас есть пронумерованные отделы, было бы легко иметь проверку UserDepartmentIs и проверку TodayIsAfter, а затем объединить их, чтобы иметь Department = 2 и Today> 15/03/2016. Если затем вы хотите выполнить проверку TodayIsBefore, чтобы вы могли завершить дату разрешения, вам нужно написать функцию TodayIsBefore.
Я не сделал это для пользовательских разрешений, но сделал это для проверки данных, но это должно работать.
источник
XACML - это решение, которое вы действительно ищете. Это тип правил, который ориентирован только на контроль доступа. XACML, стандарт, определенный OASIS, определяет три части:
Архитектура выглядит следующим образом:
Вот как выглядит ваш первый вариант использования:
Ваш второй вариант использования будет:
Вы можете объединить оба варианта использования в одну политику, используя ссылки:
И вы сделали!
Вы можете прочитать больше о XACML и ALFA из:
источник
То, что вы действительно хотите здесь, это XACML . Это в значительной степени дает вам именно то, что вы хотите. Вам не обязательно реализовывать полную архитектуру с полностью разделенными ролями ... если у вас есть только одно приложение, вы, вероятно, можете обойтись без интеграции PDP и PEP в ваше приложение с Balana а PIP - что угодно ваша существующая база данных пользователей
Теперь в любом месте вашего приложения вам нужно что-то авторизовать, вы создаете запрос XACML, который имеет пользователя, действие и контекст, и механизм XACML будет принимать решение на основе написанных вами файлов политики XACML. Эти файлы политики могут храниться в базе данных или в файловой системе, или там, где вы хотите сохранить конфигурацию. У Axiomatics есть хорошая альтернатива представлению XACML XML под названием ALFA, которое немного легче читать, чем необработанный XML, и плагин Eclipse для генерации XACML XML из политик ALFA.
источник
Мы сделали это в моей нынешней компании, и мы очень довольны результатами.
Наши выражения написаны в js, и мы даже используем их, чтобы ограничить результаты, которые пользователи могут получить, запрашивая ElasticSearch.
Хитрость заключается в том, чтобы убедиться в наличии достаточного количества информации для принятия решения, так что вы действительно можете писать любые перманенты без изменений в коде, но в то же время сохранять скорость.
На самом деле нас не беспокоят атаки с внедрением кода, поскольку разрешения пишутся теми, кому нет необходимости атаковать систему. И то же самое относится к атакам DOS, как
while(true)
примере. Администраторы системы не должны этого делать, они могут просто удалить все права доступа ...Обновить:
Что-то вроде XACML кажется лучше в качестве центральной точки управления авторизацией для организации. Наш вариант использования немного отличается тем, что у наших клиентов, как правило, нет ИТ-отдела для всего этого. Нам нужно было что-то автономное, но мы старались сохранить как можно больше гибкости.
источник