JEP 202: Nashorn Class Filter
Фильтр классов в Nashorn
| Ответственный | Sundararajan Athijegannathan |
| Тип | Feature |
| Область | JDK |
| Статус | Closed / Delivered |
| Выпуск | 8u40 |
| Компонент | core-libs / jdk.nashorn |
| Обсуждение | nashorn dash dev at openjdk dot java dot net |
| Трудоёмкость | S |
| Длительность | S |
| Рецензенты | Jim Laskey |
| Одобрен | Brian Goetz |
| Создан | 2014/05/22 06:51 |
| Обновлён | 2017/05/17 00:43 |
| Задача | 8043717 |
Аннотация
Обеспечить детальный контроль доступа к Java-классам из кода на JavaScript.
Цели
-
Предоставить Java-интерфейс для фильтрации доступа к классам,
ClassFilter, который могут реализовать Java-приложения, использующие Nashorn. -
Перед обращением к любому Java-классу из скрипта Nashorn будет запрашивать переданный ему экземпляр интерфейса
ClassFilter, чтобы определить, разрешён ли доступ. Это будет происходить независимо от того, установлен ли менеджер безопасности. -
Скрипт не должен иметь никакой возможности обойти ограничения фильтра классов, даже с помощью API рефлексии Java.
Что не является целью
Этот API не будет:
-
Фильтровать публичные методы или поля объектов, доступных скриптам. Например, если приложение, встраивающее Nashorn, открывает скриптам значение, которое является Java-объектом, то все публичные методы этого объекта можно будет вызывать из скриптов.
-
Фильтровать отдельные методы или поля.
-
Делать менеджер безопасности ненужным для скриптов. Встраивающие приложения по-прежнему должны включать управление безопасностью перед выполнением скриптов из недоверенных источников. Сама по себе фильтрация классов не создаёт полноценную «песочницу» для скриптов. Даже если выполняются только недоверенные скрипты (без дополнительных Java-классов), менеджер безопасности всё равно следует использовать. Фильтрация классов даёт более тонкий контроль сверх того, что обеспечивает менеджер безопасности. Например, приложение, встраивающее Nashorn, может запретить скриптам создавать потоки или выполнять другие ресурсоёмкие операции, которые менеджер безопасности может разрешать.
-
Обеспечивать совместимость с
ClassShutterиз Mozilla Rhino. У APIClassFilterв Nashorn не будет тех же имён пакетов, классов и методов, что у движка Mozilla Rhino. Предлагаемый API Nashorn лишь концептуально похож на APIClassShutterв Rhino.
Мотивация
В Nashorn есть несколько глобальных объектов, таких как Packages, java, org, com, javax, javafx, org, net, JavaImporter и Java, которые дают простой доступ к Java-классам из кода на JavaScript. Если менеджер безопасности включён, применяется ожидаемая политика безопасности Java: анонимным скриптам предоставляются те же разрешения, что и недоверенным классам, а скрипту, загруженному по URL, предоставляются разрешения, связанные с этим URL.
При использовании Nashorn с параметром –no-java перечисленные выше глобальные объекты пакетов не предоставляются, что фактически запрещает скриптам любой доступ к Java-пакетам и классам. Скрипт имеет либо полный доступ к Java с учётом ограничений безопасности, либо, с –no-java, никакого доступа.
Движок JavaScript Rhino обеспечивает более детальный контроль доступа с помощью определяемого пользователем класса ClassShutter. Java-приложения, встраивающие Rhino, могут открывать скриптам только часть Java-классов. Nashorn должен предоставлять аналогичный детальный Java API.
Серверные фреймворки на JavaScript — важная целевая область для движка скриптов Nashorn. Таким фреймворкам иногда приходится выполнять скрипты из недоверенных источников и поэтому ограничивать доступ к Java API. Хотя здесь помогает изоляция на основе менеджера безопасности, серверным приложениям, встраивающим Nashorn, часто нужен более тонкий контроль. API должен позволять ограничить доступ скриптов подмножеством Java-классов.
Описание
Будет определён новый интерфейс jdk.nashorn.api.scripting.ClassFilter. Приложения, встраивающие Nashorn, например серверные фреймворки на JavaScript, могут реализовать ClassFilter. Чтобы передать в Nashorn реализованный пользователем ClassFilter, клиентскому приложению придётся создавать экземпляр движка скриптов Nashorn через API, специфичный для Nashorn.
Новый API, добавленный в класс jdk.nashorn.api.scripting.NashornScriptEngineFactory:
/**
* Create a new Script engine initialized by given class filter.
*
* @return newly created script engine.
* @throws NullPointerException if {@code classFilter} is {@code null}
* @throws SecurityException
* if the security manager's {@code checkPermission}
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final ClassFilter classFilter)
/**
* Create a new Script engine initialized by given arguments.
*
* @param args arguments array passed to script engine.
* @param appLoader class loader to be used as script "application" class loader.
* @param classFilter class filter to use.
* @return newly created script engine.
* @throws NullPointerException if {@code args} or {@code classFilter} is {@code null}
* @throws SecurityException
* if the security manager's {@code checkPermission}
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter)
Новый интерфейс jdk.nashorn.api.scripting.ClassFilter:
public interface ClassFilter {
/**
* Should the Java class of the specified name be exposed to scripts?
* @param className is the fully qualified name of the java class being checked. This will not be null. Only non-array class names will be passed.
* @return true if the java class can be exposed to scripts false otherwise
*/
public boolean exposeToScripts(String className);
}
Скрипты Nashorn обращаются к Java-пакетам и классам через объект Packages и функцию Java.type. Объект Packages позволяет обращаться к Java-классам и пакетам с помощью привычного синтаксиса «через точку». Функция Java.type принимает строку с полным именем Java-типа и возвращает соответствующий объект Class. Оба этих API будут проверять, установлен ли в движке скриптов Nashorn фильтр классов. Если фильтр классов есть, интерфейс будет запрашивать его, можно ли открыть класс скриптам. Если фильтр вернёт false, функция Java.type выбросит ClassNotFoundException, а API Packages будет считать имя с точками именем пакета, а не именем класса.
Пример:
var Vector = java.util.Vector;
var Thread = Java.type(`java.lang.Thread`);
Если фильтр классов запрещает доступ к java.util.Vector и java.lang.Thread, то в первой строке java.util.Vector будет считаться именем пакета, а не будет разрешено как Java-класс, а во второй строке вызов Java.type приведёт к выбросу ClassNotFoundException.
Если установлен менеджер безопасности, Nashorn разрешает скрипту использовать API рефлексии Java (то есть java.lang.reflect и java.lang.invoke), только если у скрипта есть разрешение времени выполнения nashorn.javaReflection. Если установлен фильтр классов, Nashorn будет запрещать доступ к API рефлексии даже при отсутствии менеджера безопасности. Использовать фильтр классов при доступной рефлексии бессмысленно, потому что скрипт может обойти фильтр классов с помощью метода Class.forName(String).
Тестирование
В репозитории Nashorn более 1000 тестов скриптов Nashorn. Есть тесты, обращающиеся к API javax.script, а также к API, специфичным для Nashorn, в пакете jdk.nashorn.api.scripting. Последние будут дополнены тестами фильтра классов.
Риски и допущения
Новый API будет добавлен в существующий пакет jdk.nashorn.api.scripting. Чтобы реализовать фильтры классов, пользователям придётся использовать этот нестандартный API, специфичный для JDK.