Как оценить выражения пользователя в песочнице
Я хочу, чтобы мое приложение оценивало выражение от ненадежного пользователя, которое я буду читать из файла JSON. Такие как:
value = "(getTime() == 60) AND isFoo('bar')"
Я нашел много тем об этом здесь, на Stackru. Обычно рекомендуется использовать собственный класс Java ScriptEngine, который может читать JavaScript. Или рекомендует пользователю использовать существующую библиотеку, такую как JEXL, MVEL или любую другую из этого списка: http://java-source.net/open-source/expression-languages
Но все они, похоже, полагаются на доверенного пользователя (например, файл конфигурации, который вы пишете сами и хотите выполнить в нем некоторые скрипты). Но в моем случае я хочу, чтобы оценка моего выражения выполнялась в безопасной песочнице. Таким образом, пользователь не может сделать что-то такое простое, как:
value = "while(true)" // or
value = "new java.io.File(\"R:/t.txt\").delete()" // this works on MVEL
И заблокировать мое приложение, или получить доступ к нежелательным ресурсам.
1) Так может ли какая-либо из этих существующих библиотек быть легко настроена так, чтобы она могла работать в безопасном месте? Под "легким" я подразумеваю высокоуровневый API-интерфейс конфигурации, который я бы использовал быстрее, чем написать собственный оценщик выражений. После небольшого количества моих собственных исследований, JEXL и MVEL, похоже, отсутствуют.
2) Или существует существующий язык выражений, который предельно прост, чтобы его не мог использовать ненадежный пользователь? Все, что я нашел, очень сложны и реализуют такие вещи, как циклы, операторы импорта и т. Д. Все, что мне нужно, - это анализ математики, логических операторов и моих собственных определенных переменных и методов. Все, что находится за ее пределами, находится за пределами моей компетенции.
3) Если единственное решение - написать собственный оценщик выражений, то где я могу найти руководство по написанию согласованной модели безопасности? Я новичок в этом, и не имею представления о том, какие обычные приемы используются для внедрения кода. Вот почему я хотел избежать написания этого самостоятельно.
1 ответ
Я мог бы рекомендовать встраивать Rhino, позволяя пользователю писать javascript. Он соответствует вашим критериям в (2), идеально являясь библиотекой Java, которая позволяет вам запускать javascript (или запускать java из javascript).
Вы настраиваете контекст, и пользователь имеет доступ только к тому, что вы помещаете в контекст или делаете доступным из него. Выражения javascript могут быть такими же простыми, как простейший случай, который вы демонстрируете выше, или могут быть настолько сложными, насколько это необходимо. Внедрение Rhino и демонстрация ограниченного набора объектов было отличным способом включить все виды пользовательских сценариев в прошлом проекте, и это было несколько лет назад, Rhino уже достаточно зрел.
У вас также есть преимущество в том, что, если ваша проблема требует этого, вы вполне можете настроить его так, чтобы те же выражения успешно выполнялись на стороне клиента или сервера.
Дополнительную информацию о встраивании Rhino для выполнения своих задач можно найти по адресу http://www.mozilla.org/rhino/tutorial.html.