我编写了一个简单的RMI服务器,并为它提供了一个默认的RMISecurityManager,其中包括:
System.setSecurityManager (new RMISecurityManager());当我试图运行服务器时,它会抛出一个异常:
java.security.AccessControlException:访问被拒绝("java.net.SocketPermission“"127.0.0.1:1099”“连接,解析”)
我认为如果任何下载的代码试图连接到某个地方,安全管理器会抛出一个异常。但是在这里,当服务器本身试图做一些事情时,安全管理器正在抱怨。为什么?
下面是服务器的代码(来自Oracle教程,但我添加了RMISecurityManager):
package example.hello;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RMISecurityManager;
public class Server implements Hello {
public Server() {}
public String sayHello() {
return "Hello, world!";
}
public static void main(String args[]) {
try {
Server obj = new Server();
// * Addition *
System.setSecurityManager (new RMISecurityManager());
// Create object that will provide the remote service
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}}
我这样做:
$ javac -d类示例/*java
$ java -cp pwd/classes example.hello.Server
服务器异常: java.security.AccessControlException:访问拒绝("java.net.SocketPermission“"127.0.0.1:1099”“连接,解析”) java.security.AccessControlException:拒绝访问("java.net.SocketPermission“"127.0.0.1:1099”连接,在java.security.AccessControlContext.checkPermission(AccessControlContext.java:372) at java.security.AccessController.checkPermission(AccessController.java:559) at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) at java.lang.SecurityManager.checkConnect(SecurityManager.java:1051) at java.net.Socket.connect(Socket.java:574) at java.net.Socket.connect(Socket.java:528) at java.net.Socket.( 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:( sun.rmi.server.UnicastRef.newCall(UnicastRef.java:340) at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source) at example.hello.Server.main(Server.java:66)
更新:
我对RMISecurityManager的理解是错误的。我假设它的沙箱只自动应用于外部代码,即客户端提交供执行的代码(如Oracle RMI教程中的“计算引擎”示例)。创建以下策略允许服务器在启动时与RMI注册表进行对话,并且异常消失:
grant codeBase "file:/path/to/classes/" {
permission java.net.SocketPermission "127.0.0.1:1099", "connect, resolve";
};但是,如何使用安全管理器创建特定于下载代码的规则?
发布于 2014-01-25 22:58:08
如果使用安全管理器,还需要提供一个为您提供所需权限的.policy文件。
除非使用代码库特性,否则不需要使用RMI的安全管理器。当它被使用时,它通常用于向客户机提供类,而不是向服务器提供类,因此需要安全管理器的是客户机,而不是服务器。你可能安装它是不必要的。
https://stackoverflow.com/questions/21351657
复制相似问题