【问题标题】:Why the RMI code is throwing AccessControlException?为什么 RMI 代码会抛出 AccessControlException?
【发布时间】:2021-03-13 06:53:50
【问题描述】:

我有一个 Java 类,其中 RMI 代码编写为:

public class Test{
  public static void main(String[] args){
    System.setProperty("java.security.policy","file:/C:/myFloder/server.policy");
   
    if (System.getSecurityManager() == null) {
        System.setSecurityManager(new SecurityManager());
        log.info("Security manager installed.");
    } else {
        log.info("Security manager already exists.");
    }

    try {
        LocateRegistry.createRegistry(1099);
        log.info("java RMI registry created.");
    } catch (RemoteException e) {
        log.info("java RMI registry already exists.");
    }
    Naming.unbind("//" + serverIp + ":1099/ServletPath");
    log.info("RMI stareted successfully...!!");
  }
}

这里是 server.policy:

grant {
    permission java.security.AllPermission;
};

但是当我试图执行它时,它总是给我同样的例外。我也尝试了 stackoverflow 中的各种解决方案,但都是徒劳的。

java.security.AccessControlException: access denied ("java.net.SocketPermission" "127.0.0.1:1099" "connect,resolve")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkConnect(SecurityManager.java:1051)
    at java.net.Socket.connect(Socket.java:584)
    at java.net.Socket.connect(Socket.java:538)
    at java.net.Socket.<init>(Socket.java:434)
    at java.net.Socket.<init>(Socket.java:211)
    at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
    at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:148)
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
    at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:342)
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    at java.rmi.Naming.rebind(Naming.java:177)
    at com.ist.ivision.rmi.server.SendOnQueueImpl.initMethod(SendOnQueueImpl.java:99)
    at com.ist.ivision.rmi.server.SendOnQueueImpl.main(SendOnQueueImpl.java:143)
    at com.ist.ivision.servlet.IVisionStartup$2.run(IVisionStartup.java:124)
    at java.lang.Thread.run(Thread.java:745)

java.security.AccessControlException: access denied ("java.io.FilePermission" "filepath/A.java" "write")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkWrite(SecurityManager.java:979)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:200)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
    at java.io.FileWriter.<init>(FileWriter.java:63)

谁能告诉我我在这里做错了什么??

谢谢

【问题讨论】:

  • 当你运行你的代码时,你会得到“安装安全管理器”。或“安全管理器已存在。” ?我问的原因是因为它可能没有读取您指定的策略文件..
  • @SusanMustafa 我正在“安装安全管理器”。
  • 我认为它没有找到您的策略文件....即使 Java 没有抱怨。
  • @SusanMustafa 如何让它读取策略文件?
  • 为什么要使用 SecurityManager?如果您使用代码库功能,则仅在 RMI 中需要它。为什么要从新创建的注册表中解除绑定,因此它是空的?

标签: java rmi policy securitymanager


【解决方案1】:

查看现有的 java.policy 文件,格式看起来也不同。

// 标准扩展默认获取所有权限

grant codeBase "file:${{java.ext.dirs}}/*" {
        permission java.security.AllPermission;
};

我还会仔细检查您的自定义 .policy 文件的路径是否正确。

一个有用的 Stackoverflow 是:Java RMI AccessControlException: access denied

===== 已编辑

否则,请尝试从代码中删除 System.setProperty(),并在运行时从您的 IDE 作为运行时参数指向自定义策略文件:

删除 System.setProperty()

修改 Eclipse/Intellij 并添加运行时参数

-Djava.security.manager -Djava.security.policy=C:/myFloder/server.policy

============= 已编辑 2

尝试这样做而不是使用文件:

    Policy.setPolicy(new Policy() {
        @Override
        public boolean implies(ProtectionDomain domain, Permission permission) {
            return true; // all permissions
        }
    });

    System.setSecurityManager(new SecurityManager());

【讨论】:

  • 我也试过这种方式。我用绝对文件路径替换了“${{java.ext.dirs}}”,但它仍然给了我同样的例外@Susan Musafa
  • 我确实将 "${{java.ext.dirs}}" 替换为 "file://C:/serverpath/webapps/ROOT/WEB-INF/classes/*" 但它不是帮忙。我将 jar 文件放到 tomcat 上下文中。我该怎么做:“-Djava.security.manager -Djava.security.policy=C:/myFloder/server.policy”
  • 我的意思不是修改您的策略文件。我想知道您是否可以修改您的 System.setProperty() 以指向 file:// 而不是 file:/ 但尝试将策略文件作为运行时参数而不是在代码中指向,看看是否有帮助。至少消除可能的路径问题
  • 但我没有从 eclipse IDE 执行代码。我正在创建 jar,然后将其部署到 tomcat 容器。我如何提供运行时参数?
  • 我得到了解决方案,我需要通过Policy.getPolicy().refresh() 刷新政策,只有其余内容正确发布在我的问题中。
猜你喜欢
  • 2016-06-23
  • 2012-05-21
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多