我有一个 Java 8 应用程序,它通过 Nashorn JavaScript ScriptEngine 评估用户提供的代码。为了防止评估恶意代码,我使用以下策略启用 Java SecurityManager:
grant codeBase "file:/-" {
permission java.security.AllPermission;
};
grant {
permission java.net.SocketPermission "*", "accept,connect,resolve";
};
这允许我的主要 Java 应用程序不受限制地运行,但任何 JavaScript 代码都仅限于通过第二个授权块授予的权限。我将我的应用程序打包到一个 MyApp.jar 文件中,一般来说这可以正常工作,并且每次有人尝试java.lang.System.exit()
从我的 ScriptEngine 等调用时都会引发 AccessControlException。
现在解决问题 - 如果我将 jar 文件放在网络共享 ( \\global\fs\Technology\Tools\MyApp.jar
) 上,那么我的应用程序将无法加载,因为“AllPermission”授权块似乎与我的代码库不匹配。有没有其他人遇到过这个问题并且知道如何解决它 - 这只发生在网络驱动器上,而不是如果我将它放在其他任何地方。
这是调试输出 -
java -Djava.security.manager -Djava.security.policy=mypolicy -Djava.security.debug=access -jar \\global\fs\Technology\Tools\MyApp.jar
这会导致以下错误消息:
access: access allowed ("java.io.FilePermission" "\\global\fs\Technology\Tools\MyApp.jar" "read")
access: access allowed ("java.util.PropertyPermission" "os.version" "read")
access: access allowed ("java.util.PropertyPermission" "swing.useSystemFontSettings" "read")
access: access allowed ("java.util.PropertyPermission" "os.name" "read")
access: access allowed ("java.util.PropertyPermission" "java.home" "read")
access: access allowed ("java.io.FilePermission" "C:\Program Files\Java\jre1.8.0_121\lib\swing.properties" "read")
access: access allowed ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")
access: access allowed ("java.util.PropertyPermission" "os.version" "read")
access: access allowed ("java.util.PropertyPermission" "user.dir" "read")
access: access allowed ("java.io.FilePermission" "C:\etc\release" "read")
access: access allowed ("java.io.FilePermission" "\etc\release" "read")
access: access allowed ("java.util.PropertyPermission" "swing.showFromDoubleBuffer" "read")
access: access allowed ("java.util.PropertyPermission" "swing.nativeErase" "read")
access: access denied ("java.awt.AWTPermission" "showWindowWithoutWarningBanner")
access: access allowed ("java.util.PropertyPermission" "awt.appletWarning" "read")
access: access allowed ("java.util.PropertyPermission" "java.home" "read")
access: access allowed ("java.util.PropertyPermission" "sun.awt.nopixfmt" "read")
access: access allowed ("java.util.PropertyPermission" "swing.logDoubleBufferingDisable" "read")
access: access allowed ("java.util.PropertyPermission" "swing.ignoreDoubleBufferingDisable" "read")
access: access allowed ("java.lang.RuntimePermission" "createClassLoader")
access: access allowed ("java.lang.RuntimePermission" "createClassLoader")
access: access allowed ("java.lang.RuntimePermission" "accessClassInPackage.sun.reflect.misc")
.. (removed for brevity)
access: access allowed ("java.util.PropertyPermission" "os.name" "read")
access: access allowed ("java.util.PropertyPermission" "java.util.prefs.PreferencesFactory" "read")
access: access allowed ("java.util.PropertyPermission" "os.name" "read")
access: access allowed ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")
access: access denied ("java.lang.RuntimePermission" "preferences")
Exception in thread "AWT-EventQueue-0" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "preferences")
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.util.prefs.Preferences.userRoot(Unknown Source)
at e.<init>(Unknown Source)
at e.<init>(Unknown Source)
at MyApp.<init>(Unknown Source)
at a.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
我什至尝试完全按照上面的方式引用 codeBase,但我仍然遇到同样的问题:
grant codeBase "file:\\global\fs\Technology\Tools\MyApp.jar" {
permission java.security.AllPermission;
};
更新进一步的调试显示了Java中的错误?我已经在策略文件中完全匹配了“Active CodeSource”,但它仍然拒绝它:
grant codeBase "file:/-" {
permission java.security.AllPermission;
};
grant codeBase "file://global/fs/Technology/Tools/MyApp.jar" {
permission java.security.AllPermission;
};
grant {
permission java.net.SocketPermission "*", "accept,connect,resolve";
};
通过policy
调试,我看到以下内容(我确实注意到file:/-
更改为只允许我当前的 C: 驱动器):
C:\Users\Default> java -Djava.security.manager -Djava.security.policy=mypolicy -Djava.security.debug=policy -jar \\global\fs\Technology\Tools\MyApp.jar
policy: evaluate codesources:
Policy CodeSource: (file:/C:/- <no signer certificates>)
Active CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
policy: evaluation (codesource) failed
policy: evaluate codesources:
Policy CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
Active CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
policy: evaluation (codesource) failed
policy: evaluate codesources:
Policy CodeSource: (null <no signer certificates>)
Active CodeSource: (file://global/fs/Technology/Tools/MyApp.jar <no signer certificates>)
policy: evaluate principals:
Policy Principals: []
Active Principals: []
policy: granting ("java.net.SocketPermission" "*" "connect,accept,resolve")
如您所见,它正在将“Policy CodeSource”与“Active CodeSource”进行比较,并说即使它们相同也不匹配?!?由于它们不匹配,因此我的通用授权块只授予有限的权限。
只有当我当前的工作目录与我的 JAR 文件位于不同的驱动器或文件系统上时,才会出现这种情况。
无论路径如何,都不能授予“MyApp.jar”权限吗?