运行 JavaJava 中的脚本:文件权限被拒绝

Running Javascript in Java: FilePermission denied

运行 JavaJava 中的脚本,我在读取和写入时都被拒绝访问 FilePermission。当 Java 脚本访问执行某些文件操作的 Java 方法时,就会发生这种情况。我的 Java Swing GUI 程序本身在本地磁盘上读写文件没有问题。

使用以下方法评估脚本:

URL url = new URL(scriptURL);
InputStream is = url.openStream();
Reader reader = new InputStreamReader(is, Constants.DEFAULT_CHARSET);
engine.eval(reader);

我可以通过将以下内容添加到 Java 默认值 java.policy

来解决这个问题
grant {
    permission java.io.FilePermission "<<ALL FILES>>", "read, write";
};

这不是一个平等的解决方案。它需要我程序的所有用户将其添加到他们自己的 Java 策略中。

如果我提供了我自己的 Java 策略文件,这可以在 运行 JAR 时使用。但是,由于该程序是通过 Java Web Start 执行的,因此这不是一个选项。 运行 Java 命令行上的 Web Start 可以提供额外的 java 策略文件,但这不是一个用户友好的选项。添加带有额外 java 策略文件的 JNLP 资源 属性 不起作用,因为我的 JNLP 未签名(虽然我的 JAR 已签名)。

SEVERE: http://machine/path/to/someJavaScript.js: access denied ("java.io.FilePermission" "/home/username/.program/cache/image8761533877202123654.img" "read")
java.security.AccessControlException: access denied ("java.io.FilePermission" "/home/username/.program/cache/image8761533877202123654.img" "read")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:457)
at java.security.AccessController.checkPermission(AccessController.java:884)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at com.sun.javaws.security.JavaWebStartSecurity.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkRead(SecurityManager.java:888)
at sun.awt.SunToolkit.checkPermissions(SunToolkit.java:912)
at sun.awt.SunToolkit.getImageFromHash(SunToolkit.java:737)
at sun.awt.SunToolkit.getImage(SunToolkit.java:752)
at javax.swing.ImageIcon.<init>(ImageIcon.java:159)
at javax.swing.ImageIcon.<init>(ImageIcon.java:186)
at com.company.gui.ImageHelperStore.get(ImageHelperStore.java:366)
at com.company.gui.BaseComponent.getIcon(BaseComponent.java:1046)
at com.company.gui.GUIScripter$Helper.getIcon(GUIScripter.java:152)
at jdk.nashorn.internal.scripts.Script$\^eval\_.:program(<eval>:32)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:636)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:229)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:387)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:437)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:401)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:397)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:147)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249)
at com.company.gui.GUIScripter.initializeScript(GUIScripter.java:392)
at com.company.gui.GUIScripter.postInitialize(GUIScripter.java:346)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:301)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)e here

如果您从字符串或任意 java.io.Reader 实例加载脚本,则 nashorn 脚本引擎会将脚本视为 "untrusted",因此仅向其授予 "sandbox" 权限(无论在您的安全策略中没有 "codeBase" 的权限)。但是,如果你想为你的 jar 文件赋予相同的权限(即在你的脚本中继承 jar 文件的权限),那么你必须使用 jdk.nashorn.api.scripting.URLReader (https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/URLReader.html)[=15= 加载脚本]

示例代码

您可能需要将以下文件复制到您的主目录下。要编译和 运行 这个,你可以使用下面的 run.sh 脚本。此示例使用 URLReader 加载脚本。所以脚本"inherits"权限被授予jar文件。

文件:Main.java

import javax.script.*;
import java.net.URL;
import jdk.nashorn.api.scripting.URLReader;

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager m = new ScriptEngineManager();
        ScriptEngine e = m.getEngineByName("nashorn");
        e.eval(new URLReader(Main.class.getResource("test.js")));
    }
}

文件test.js

print("about to exit...");
java.lang.System.exit(0);

文件test.policy

grant codeBase "file:${user.dir}/test.jar" {
    permission java.security.AllPermission;
};

文件run.sh

javac Main.java
jar cvf test.jar Main.class test.js
java -Djava.security.manager -Djava.security.policy=test.policy -cp test.jar Main