在Java中运行Javascript:FilePermission被拒绝

Running Javascript in Java: FilePermission denied

本文关键字:FilePermission 拒绝 Javascript Java 运行      更新时间:2023-09-26

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

使用以下方法评估脚本:

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执行的,因此这不是一个选项。在命令行上运行JavaWebStart可以提供额外的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.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.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

如果从String或任意java.io.Reader实例加载脚本,那么nashorn脚本引擎会将该脚本视为"不受信任",因此只授予它"沙盒"权限(安全策略中没有"codeBase"的任何权限)。但是,如果您希望对jar文件具有相同的权限(即,在脚本中继承jar文件的权限),则必须使用jdk.nashorn.api.scripting.URLHeader加载脚本(https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/URLReader.html)

样本代码

您可能希望在主目录下复制以下文件。要编译并运行此程序,您可以使用下面的run.sh脚本。此示例使用URLHeader加载脚本。因此,脚本"继承"了授予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);

文件测试.policy

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

文件运行.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