LINUX.ORG.RU

Eval в java

 ,


0

2

Здравствуйте. Можно ли строку выполнить как функцию?

Например заданы переменные

String k1;
String k2;
И вот строка загружаемая с сервера
"k1 = \"test\"; k2 = \"tset\"";



Последнее исправление: jessgt (всего исправлений: 1)

Лучше всего с сервера грузить XML, а не Java-код. Сервер взломают, встроят туда какой-нибудь майнер и будет эта программа у пользовтелей майнить в угоду хакеру.

Eval'а в Java, слава богу, нет, так как Enterprise'овому языку не нужна такая дырень в безопасности. Это же не PHP или Python.

Можно использовать JavaScript'овский eval, доступный где-то в дебрях javax. Для Android, конечно, нужно будет подключить доп. библиотеку:

https://stackoverflow.com/questions/42128648/how-to-use-scriptenginemanager-i...

Ещё может быть возможно использовать встроенный веб-движок для JavaScript'овского eval'а.

Но лучше переделать сервер.

EXL ★★★★★
()

Выполнять что-то с сервера в любом случае не надо, вдруг злодеи угонят сам сервак и будут передавать команду «удалить все, до чего дотянешься».

Лучше и серваком, и андроидом стандартный JSON гонять. Когда-то ему в плюсы записывалось, что можно сделать eval, вот вам и сериализация. А на сегодня это стандарт, в Java есть библиотека gson

Сервак

Gson gson = new GsonBuilder().create();
Map<String, String> obj = new LinkedHashMap<String, String>();
obj.put("k1", "test");
obj.put("k2", "tset");

String toTransmit = gson.toJson(obj);

Андроид

Gson gson = new GsonBuilder().create();
Map map = gson.fromJson(strFromServer);

Можно еще класс завести с двумя полями, k1 и k2, не придется с мапами заморачиваться.

Если менять сервак не вариант, переменные нужно регулярками выкусывать.

String strFromServer = "k1 = \"test\"; k2 = \"tset\"";
Pattern pattern = Pattern.compile("k1 = \"(\w+)\"; k2 = \"(\w+)\"");
Matcher matcher = pattern.matcher(strFromServer);
if (matcher.find()) {
  String k1 = matcher.group(1);
  String k2 = matcher.group(2);
}

Код из головы, наверняка с ошибками, но идея понятна.

anonymous
()
Ответ на: комментарий от EXL

Eval'а в Java, слава богу, нет, так как Enterprise'овому языку не нужна такая дырень в безопасности. Это же не PHP или Python.

Можно использовать JavaScript'овский eval, доступный где-то в дебрях javax.

Знатно поделил на 0 самого себя. Так в Джаве есть eval, пусть и где-то заныканный, или нет?

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

eval-ить Java пока что нельзя.

eval-ить Javascript можно.

https://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("print('Hello World!');");

С незапамятных времен в JRE есть движок Rhino, году в 11 появился второй, Nashorn.

anonymous
()
Ответ на: комментарий от anonymous

Какая разница, через что тебя поимеют какиры? Твой пример показывает, как легко и просто сделать каку в интерпрайзной Джава, «в которой нет eval, ко-ко-ко».

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Ваш ответ показывает, что вы не поняли вопрос.

Также и авторы других ответов, рассказывающие об «опасности eval на сервере».

Причём тут вообще сервер? Если программа работает в Android.

Partisan ★★★★★
()
Ответ на: комментарий от Begemoth

Не лучше десерилиализовать подписанные блобы передаваемые по безопасному каналу? Ну т.е. сериализация или эвал это один хрен дыра, но если всё верифицируется, то какиры не пролезут (пока сервер не поимеют, но там уже делай что хочешь). Можно подписывать эцп, тогда какиры поимев сервер не пролезут на устройства (пока не перехватят эцп, поэтому подписывание блобов делать на отключённом от сети устройстве). Короче было бы желание.

anonymous
()
Ответ на: комментарий от Legioner
        var jShell = JShell.create();
        jShell.eval("String k1, k2;");
        jShell.eval("k1 = \"test\"; k2 = \"tset\";");
        var k1 = jShell.variables().filter(v -> v.name().equals("k1")).findAny().get();
        System.out.println(jShell.varValue(k1));
Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)
Ответ на: комментарий от Legioner
        var scriptEngineManager = new ScriptEngineManager();
        var scriptEngine = scriptEngineManager.getEngineByName("Java");
        var evalString = "k1 = \"test\"; k2 = \"tset\";";
        scriptEngine.eval()
        var evalClass = (Class<?>) scriptEngine.eval("" +
                "class Example {" +
                "    String k1, k2;" +
                "    Example() {" +
                "    }" +
                "    void run() {" +
                "        " + evalString + "" +
                "    }" +
                "}");
        var evalCtor = evalClass.getDeclaredConstructor();
        evalCtor.setAccessible(true);
        var evalObj = evalCtor.newInstance();
        Method evalRunMethod = evalClass.getDeclaredMethod("run");
        evalRunMethod.setAccessible(true);
        evalRunMethod.invoke(evalObj);
        Field evalK1Field = evalClass.getDeclaredField("k1");
        evalK1Field.setAccessible(true);
        var k1 = evalK1Field.get(evalObj);
        System.out.println(k1);

Требует org.patrodyne:patrodyne-scripting-java:1.0.0

Legioner ★★★★★
()
Ответ на: комментарий от Legioner
        var javaCompiler = ToolProvider.getSystemJavaCompiler();
        var fileManager = javaCompiler.getStandardFileManager(null, ENGLISH, UTF_8);
        var fileSystem = Jimfs.newFileSystem(Configuration.unix());
        var evalString = "k1 = \"test\"; k2 = \"tset\";";
        Files.writeString(fileSystem.getPath("/Example.java"), "" +
                "public class Example implements Runnable {" +
                "    public String k1, k2;" +
                "    public void run() {" +
                "        " + evalString + "" +
                "    }" +
                "}");
        var sources = fileManager.getJavaFileObjects(fileSystem.getPath("/Example.java"));
        javaCompiler.getTask(null, fileManager, null, null, null, sources).call();
        var bytecode = Files.readAllBytes(fileSystem.getPath("/Example.class"));
        var classLoader = new ClassLoader() {
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                if (name.equals("Example")) {
                    return defineClass(name, bytecode, 0, bytecode.length);
                }
                return super.findClass(name);
            }
        };
        var exampleClass = classLoader.findClass("Example");
        var exampleObj = (Runnable) exampleClass.getConstructor().newInstance();
        exampleObj.run();
        System.out.println(exampleClass.getField("k1").get(exampleObj));

Требует com.google.jimfs:jimfs:1.1

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)
Ответ на: комментарий от EXL

Сервер взломают, встроят туда какой-нибудь майнер и будет эта программа у пользовтелей майнить в угоду хакеру.

Можно ограничить права выполняемому коду, например запретить сетевые соединения.

Legioner ★★★★★
()

Для этих дел можно реализовать небольшой внешний скриптовый язык.

За одно огородить от ненужного. Или тот же Рино заюзать.

nihirash ★★★
()

Посмотрите на задачу с другой стороны. Не инициализируйте переменные, а заполняйте их значениями. Например, апи возвращает респонс и оттуда прочитайте значения.
Eval is evil.

duck
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.