2012-02-16 41 views
1

我有一個啓動第二個JVM的項目。目前我正在使用RMI在兩者之間進行通信。在我自己的機器上運行良好。只有本地主機的RMI?

我需要能夠部署在Windows 7機器這個項目,我沒有權限修改防火牆規則。

註冊表(從第一JVM中推出了高任意端口上)被阻止從在這些機器上打開一個服務器套接字。

有沒有辦法來限制RMI只能聽本地連接;這樣Windows防火牆會很酷嗎?

另外,有將需要很少的功能變化的良好替代IPC的方法?

乾杯。

+0

這就是Web服務(在8080端口上工作)獲得普及的原因。 – 2012-02-16 08:28:51

+0

我不知道這將如何幫助?我可以在兩者之間打開一個本地http連接,但是在那個階段,我最好只是在套接字上運行一個對象流呢? – FlightOfStairs 2012-02-16 10:00:02

回答

3

這比第一次看起來更復雜。需要的是限制註冊表正在監聽的IP 地址,但不限制端口。問題是RMI註冊實現程序(rmiregistry)實際上並沒有提供任何機制來限制它監聽的IP地址;它總是監聽每個可用的網絡接口。只有兩種實際的限制機制:

  1. 使用防火牆規則。這是一種正常的技術,但它需要在部署過程中進行配置。
  2. 使用適用的限制,以恰到好處的IP地址(即localhost127.0.0.1)RMI註冊的一個特殊版本,因爲Windows 抱怨只能從本地機器達到插座。

這第二個選項是什麼我就勾勒出。這實際上很簡單,因爲您可以將大部分複雜性委託給現有的類。

import java.io.IOException; 
import java.net.*; 
import java.rmi.server.*; 
import java.rmi.registry.LocateRegistry; 

public class RestrictedRMIRegistry implements RMIServerSocketFactory { 
    public static void main(String... args) throws IOException { 
     int port = (args.length == 0 ? 1099 : Integer.parseInt(args[0], 10)); 
     RMIClientSocketFactory csf = RMISocketFactory.getDefaultSocketFactory(); 
     RMIServerSocketFactory ssf = new RestrictedRMIRegistry(); 

     LocateRegistry.createRegistry(port, csf, ssf); 
    } 

    public ServerSocket createServerSocket(int port) throws IOException { 
     // Tricky bit; make a server socket with bound address 
     return new ServerSocket(port, 0, InetAddress.getLocalHost()); 
    } 
} 

這和正常rmiregistry實現之間唯一的區別是,它使用了客戶端和服務器套接字工廠的默認值。

+0

正是我在找的 – FlightOfStairs 2012-02-22 14:38:12

+0

我發現這對於一個類似的問題非常有幫助,我爲了安全目的想限制RMI到本地主機,但是我發現我還需要限制端口1098套接字。做完b y將這個相同的套接字工廠提供給遠程類的構造器,例如 公共類RemoteStatistics擴展了UnicastRemoteObject { 私人RemoteStatistics()將拋出RemoteException { 超(1098, 空, RestrictableRMIRegistry.getInstance()); } – Fanjita 2014-04-29 11:16:48

+0

對不起,我是一個有SO註釋標記的noob,我努力讓這些代碼格式正確。 – Fanjita 2014-04-29 11:23:16

0

好的替代方法稱爲HTTP上的Web服務,通​​常用於出站連接。

問題在於入站連接。我認爲,「正確的」架構是當部署在防火牆後面的進程通過第三進程互相通信時 - 即安裝在入站HTTP連接不受限制的地方的服務器。因此,防火牆後面的2個組件僅執行到服務器的出站HTTP連接。

+0

我不需要這樣做。系統的所有部分都在一臺機器上運行,並且不需要外部資源。問題是Windows防火牆阻止了rmiregistry,這是我用於本地IPC的。 – FlightOfStairs 2012-02-16 09:48:34

0

嘗試打開註冊表(或涉及您的方案中的任何其他Java進程),當java.rmi.server.hostname屬性設置爲127.0.0.1

+0

這不是一個壞主意,但它不會影響註冊表,只會從其中設置屬性的JVM導出其他遠程存根,因爲註冊表存根本地構建,而不是遠程獲取。限制SocketPermission「接受」的.policy文件是另一種可能性。 – EJP 2012-02-22 09:26:20

+0

嗯,你說得對。當我使用該集合運行'rmiregistry'時,它仍然打開一個敞開的端口。 :-(我知道如何解決,但是需要一點點寫,因爲它需要代碼 – 2012-02-22 09:47:47

+0

'java.rmi.server.hostname'不控制監聽端口,它控制寫入存根。'LocateRegistry.getRegistry()'從你提供的host:port本地構造一個Registry stub,所以在註冊表的JVM上對java.rmi.server.hostname的設置不會對該stub產生任何影響。獲取註冊表或任何其他遠程對象來打開綁定到127.0.0.1的端口時,必須指定一個在導出時會這樣做的'RMIServerSocketFactory'。 – EJP 2012-02-22 09:57:33