Java RMI访问控制异常:拒绝访问

19

在我尝试启动我编写的 RMI 应用时,出现了 AccessControlException: access denied 错误。如果我在默认端口 1099 或其他动态端口上打开它,我都无法解决这个异常问题。我的策略文件目前授权所有权限(会在应用程序完成后改变)。

我不知道哪里出了问题,任何帮助都将非常有用。

我的代码:

public class Main {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) throws RemoteException, AlreadyBoundException, MalformedURLException {
     if (System.getSecurityManager() == null)
     {
        System.setSecurityManager ( new RMISecurityManager() );
     }

     CreditCardServer ccs = new CreditCardServer();

     int port = 1099;

     try {
        port = Integer.valueOf(args[0]);
        }
     catch (Exception e)
        {
        System.out.println("Invlaid Port");
        }

     if (((port <= 65535) && (port >= 49152)) || port ==1099)
     {
     System.out.println("Valid Port");
     }
     else
     {
         port = 1099;
        System.out.println("Port not in Dynamic Range 49152<-->65535");
     }

     System.out.println(port);

     LocateRegistry.createRegistry(port);

     LocateRegistry.getRegistry().bind("CreditCardServer", ccs);

     while (true)
     {
        //hum?
     }
}

}

堆栈跟踪

vega3 [ia32.linux] 23% java -Djava.security.policy=wideopen.policy -jar "BookStore-CreditCardServer.jar 65000"

有效端口

65000

Exception in thread "main" java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:342)
        at java.security.AccessController.checkPermission(AccessController.java:553)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.lang.SecurityManager.checkConnect(SecurityManager.java:1051)
        at java.net.Socket.connect(Socket.java:536)
        at java.net.Socket.connect(Socket.java:492)
        at java.net.Socket.<init>(Socket.java:389)
        at java.net.Socket.<init>(Socket.java:203)
        at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
        at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
        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:340)
        at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
        at bookstorecreditcardserver.Main.main(Main.java:56)

我的策略文件

grant {
// Allow everything for now
permission java.security.AllPermission;
};

你能在你的机器上运行nmap来确保没有其他程序正在使用该端口吗?(例如,你之前运行过这个程序,但它没有干净地退出。) - Dave
3个回答

30

我一整天都卡在这个问题上(弄清楚我必须从命令行启动rmiregistry后),试图让它在Eclipse中本地运行,最终解决了。以下几点建议可以避免其他人遭遇同样的命运:

1- 正确分配策略文件,可以使用命令行标志:

java -Djava.security.policy=/home/.../<filename>.policy ...
或者直接将这段代码放入您的代码中:
System.setProperty("java.security.policy","file:///home/.../<filename>.policy");
你也可以将它放在与项目根目录相同的文件夹中,以缩短URI的长度。
file:./<filename>.policy

(使用相对URI而不是绝对URI - 直到今天我才真正理解这个)。

2 - 确保策略文件的格式正确,例如:

grant codeBase "file:<path>/bin/-" {
    permission java.security.AllPermission;
};

这应该是指您的二进制文件所在的文件夹!有关策略文件格式的详细说明在此处

就这样了,我还建议您看一下这个教程,我发现它对于入门很有帮助。


+1 感谢您对这个虽然老旧但仍然非常有价值的问题进行了详尽的回答,Nauta和wecome。 - Maarten Bodewes
策略文件链接格式的说明已过时。 - BlueDolphin
2
我该如何获取“security.policy”文件的正确路径? - CodyBugstein

3

基本上,我很蠢,我认为因为Java没有抱怨,它已经找到了.policy文件,结果发现只有将一个新的副本移动到工作目录中才能解决问题 :-D


将.policy文件的新副本移动到工作目录中。你所说的新副本是什么意思?你之前不是已经在项目的根目录下有了一个副本吗?在根文件夹中创建另一个策略文件是如何解决问题的? - Sam

0
我发现大部分关于这个主题的回答都含糊不清且无用,我花了几个小时来调试。很可能是因为策略文件格式不正确或者你没有将其正确设置为命令行参数导致错误。
如果你遇到了一个 java.security.AccessControlException: access denied ("java.net.SocketPermission" "127.0.0.1:1099" "connect,resolve") 错误:
  1. 创建一个包含所有权限的安全策略文件,只是为了测试

grant codeBase "file:/-" { permission java.security.AllPermission; };

  1. 将此安全文件用于客户端和服务器,以使它们正常运行。

  2. 确保你没有任何错别字。我花了几个小时来找出为什么它不起作用,最后发现我把 -Djava.rmi.security.policy 错误地键入成了-Djava.security.policy=...

对于我们只想让 Oracle 的 RMI 教程正常运行的人来说,这个安全策略已经足够了。

你的回答基本上与六年前发布的这个回答几乎相同,而且也不含糊也不无用。否则你的回答也是如此。 - user207421
在调试了数小时之后,我可以向您保证,这个问题需要更多的答案。我发现这行代码特别地过于复杂化了这个问题:“这应该指向您的二进制文件所在的文件夹!” - Peter Kaminski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接