RMISecurityManager沙箱

时间:2014-01-25 14:17:15

标签: java rmi

我写了一个简单的RMI服务器并给它一个默认的RMISecurityManager

System.setSecurityManager (new RMISecurityManager());

当我尝试运行服务器时,它会引发异常:

  

java.security.AccessControlException:访问被拒绝(“java.net.SocketPermission”“127.0.0.1:1099”“connect,resolve”)

我认为如果任何下载的代码试图连接某个地方,安全管理器会抛出异常。但是,当服务器本身尝试执行某些操作时,安全管理器正在抱怨。为什么呢?

这是服务器的代码(来自Oracle RMI教程,但我添加了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 classes example / * java

$ java -cp pwd / classes -Djava.rmi.server.codebase = file:pwd / classes / example.hello.Server

服务器异常:java.security.AccessControlException:拒绝访问(“java.net.SocketPermission”“127.0.0.1:1099”“connect,resolve”) java.security.AccessControlException:拒绝访问(“java.net.SocketPermission”“127.0.0.1:1099”“connect,resolve”)     at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)     at java.security.AccessController.checkPermission(AccessController.java:559)     在java.lang.SecurityManager.checkPermission(SecurityManager.java:549)     在java.lang.SecurityManager.checkConnect(SecurityManager.java:1051)     在java.net.Socket.connect(Socket.java:574)     在java.net.Socket.connect(Socket.java:528)     在java.net.Socket。(Socket.java:425)     在java.net.Socket。(Socket.java:208)     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)     在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";
};

但是如何使用安全管理器创建特定于下载代码的规则?

1 个答案:

答案 0 :(得分:1)

如果您使用安全管理器,则还需要提供.policy文件,该文件为您提供所需的权限。

除非您使用代码库功能,否则您不需要使用RMI的安全管理器。当使用它时,它通常为客户端而不是服务器提供类,因此客户端需要安全管理器而不是服务器。你可能不必要地安装它。