4

我有一个小 Java Applet,但我遇到了一个烦人的问题。我已经使用 jarsigner 工具(按照这些说明)用我自己的密钥库签署了我的 JAR 。

Java Applet 下载一个签名的 JAR 并尝试使用URLClassLoader的扩展类来启动它。这个 JAR 尝试执行这行代码:

ClassLoader.getSystemClassLoader().getResource("aResource");

它失败并通过以下方式完成大型堆栈跟踪:

Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getClassLoader")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
    at java.security.AccessController.checkPermission(AccessController.java:555)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1476)
    at test.SecondJAR.main(SecondJAR.java:8)

(test.SecondJAR第8行对应getResource(...)方法

启动 Java Applet 时,如果用户信任发布者,则会提示用户接受证书:

给用户的消息

即使我接受它,也发生了异常。即使我安装了证书,提示信息被自动接受了,还是出现了异常。

我也试过这个:

AccessController.doPrivileged(new PrivilegedAction<Object>() {
    public Object run() {
        ClassLoader.getSystemClassLoader().getResource("aResource");
        return null;
    }
});

它失败了,同样的例外。

任何帮助,将不胜感激!

4

2 回答 2

8

终于我找到了答案!

我遵循了Andrew Thomson的指导方针,并创建了一个自定义SecurityManager。我的小安全经理看起来像这样:

private class MySecurityManager extends SecurityManager {
    @Override
    public void checkPermission(Permission perm) {
        return;
    }
}

它是一个接受所有权限的被忽视的安全管理器。应该改进它只允许在运行时获取系统类加载器。

start()为了使用我丑陋的 SecurityManager,我在 Java Applet方法的开头添加了这些行:

SecurityManager sm = new MySecurityManager();
System.setSecurityManager(sm);

使用此解决方法,所有过程都按预期工作!

也许还有其他(更好的)解决方案,但它对我有用。

谢谢你们!

于 2012-07-03T14:42:42.773 回答
2

问题是 JRE 只认为原始代码库中的代码是可信的。两种可能的解决方案是:

  1. 设置一个自定义安全管理器,允许新代码拥有所需的权限。
  2. 将新代码包装在一个PrivilegedAction& 从方法中调用它AccessController.doPrivileged(..)(我只是想到一种可能性,不确定我是否理解它的范围,完全未经测试)。
于 2012-07-03T09:13:27.903 回答