java - 如何同时使用具有加密(ssl)和xinetd的JRMP(RMI)?

标签 java ssl rmi xinetd

因此,我正在滚动自己的基于Java的应用程序服务器(因为Glassfish等人不适用于非基于Web的应用程序),当然,加密是绝对必要的。因此,我使用标准的SslRMIClientSocketFactorySSLRMIServerSocketFactory编写了一个基本的ssl解决方案。到目前为止,一切都很好。但是,我还有其他一些问题,例如允许但不要求使用客户端证书(就像在ssh进入系统时一样),但是我愿意考虑另一天的练习。

但是,在我注意到自2005年左右“ Java 5.0”问世以来,我们显然对在基于'nix的解决方案上使用xinetd有所帮助。在我看来,这样做的“新”帮助是能够通过System.inheritedChannel从较低级别(如xinetd)“继承”套接字信息的能力。

我认为我需要一个在RMI解决方案中一起使用加密和xinetd的示例,并在The New RMI中找到了不错的文章-至少,如果不是该示例代码应该附带的话,那将很棒文章丢失。我猜有点烂。 (有人有副本吗?!)文章中可见的示例太不完整,并且文本依赖于您拥有示例代码的事实。那好吧。简而言之,我不太了解-使用System.inheritedChannel显然不像将其插入到您现有的RMI Registry相关代码中那样简单-您显然必须创建一个套接字工厂,或者也许我没有得到它-因此,寻找一个例子。

所以我去打猎。我发现Apache的工作人员做了类似的事情,在这里RMI Service Exporter中对此进行了描述,但是,它使用的是我宁愿避免的技术-SpringBeans。而且,坦率地说,这是一个不平凡的例子,我对如何在工作中使用这种解决方案感到迷茫。

我一直在寻找,发现乍一看像一个很棒的解决方案,名为InitializeRegistry的脸红,但是它根本没有任何对SSL的引用,我一无所获。例如,它描述为:


  创建并导出注册表(使用继承的通道,如果有,如下所示),并将指定的名称绑定到该注册表中的指定代理。


我的问题是语言。特别是,我没有使用代理,即使我使用了代理,我也不知道为什么这很重要。而且我认为我将对象绑定到RMI注册表,而不仅仅是名称。也许如果某人可以清理自己在做什么,这就是一个很好的例子……

最后,我偶然发现了一个很棒的答复-这是有史以来最糟糕的答复-就在StackOverflow上,谈论Java RMI, SSL, and compression.压缩并不能满足我的需求,但这是一个很有启发性的讨论。不过,我看不出它如何帮助我理解如何同时将RMI与SSL和xinetd一起使用...

谢谢。

更新:

为了回应EJP提出的答案(我非常感谢),我从上面引用的InitializeRegistry.java示例开始。我将accept()方法更新为:

      .
      .
      .
      /* Here we wrapper our socket with SSLSocketFactory.createSocket()

         Some open questions I have are whether the arguments to createSocket()
         are all _inbound_ in nature. Here's the basic call:

            SSLSocketFactory.createSocket(socket, host, port, auto-close);

         I PRESUME args are for the REMOTE host, not "us?"

            REMOTE: serverSocket.getInetAddress()
            LOCAL:  serverSocket.getLocalAddress()

            REMOTE: serverSocket.getPort()
            LOCAL:  serverSocket.getLocalPort()

         Who Knows about auto-close?! I'll try it and see if it works OK.
      */

      boolean autoClose = true;

      return (Socket)SSLSocketFactory.createSocket(serverSocket.accept(),
       serverSocket.getInetAddress().getHostAddress(),
       serverSocket.getLocalPort(),
       autoClose).accept();

      //return serverSocket.accept();
   }


但是,此代码无法编译,并抱怨:


createSocket()不能从静态上下文中调用-我找不到任何解决方案
它找不到“符号”“ .accept()”-两者中的第二个。


删除最终的.accept()可使错误计数减少至无法从此代码的静态上下文使用“非静态方法createSocket()”。但是,当我尝试从类中删除“ static”时,它遍地都是,无法使用普遍存在的“ this”引用。 OTOH,我不确定如何使SSLSocketFactory.createSocket()保持静态!

...可以安全地假定用于访问已传递套接字(!!)的一个accept()是足够的,并且不需要我尝试包含的下一个setUseClientMode(false)吗?嗯...

我很乐意尝试一下,看看是否可以将其构建成这个版本。

顺便说一句,我想稍后再使用InitializeRegistry.java ...是吗?

进一步思考...。

我意识到channel可能是一个不好的起点,然后回到“第一原理”,发现当它第一次使用通过System.inheritedChannel给出的ServerSocket并将其转换为,所以覆盖ServerSocketFactory的想法是“很多工作”。然后它就撞到了我:


  这里的全部目的是尝试确保未经请求的连接请求到达正在侦听的目标。但不仅如此,注册表中必须有一个对象才能使它有用,为此,也需要创建该对象的任何对象。因此,确保创建对象的代码作为系统服务运行,而不用担心将其作为网络服务运行,这将是同样容易的事情。


因此,我正在踢。 ...似乎删除该问题似乎很可耻,因为这可能会为其他人提供指导-这是所有StackOverflow中唯一涉及此主题的查询。

再次感谢。

最佳答案

我看不到DelayedAcceptServerSocketFactory的含义,这有点过头了,但是基本技术如下:


编写一个RMIServerSocketFactory返回一个ServerSocket的覆盖,该覆盖将覆盖accept()方法以委托给来自继承通道的ServerSocket
在该accept()方法返回之前,通过Socket将接受的SSLSocket包装在SSLSocketFactory.createSocket(Socket, ...)中,并在该套接字上调用setUseClientMode(false)


瞧!现在,您的RMI注册表由xinetd启动,并向您的注册表客户端讲SSL。假设这就是您想要的,您的客户端现在可以查找该注册表,只要他们通过LocateRegistry.getRegistry(host, port, csf)访问它即可。

同样,您的服务器可以绑定到它,只要它们以相同的方式访问它即可。

现在,使用SslRMI *套接字工厂创建远程对象,然后照常将它们绑定到注册表。

做完了

关于java - 如何同时使用具有加密(ssl)和xinetd的JRMP(RMI)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9474442/

相关文章:

java - 如何测量通过 RMI 发送的对象的大小?

java - 可以导出 UnicastRemoteObject 然后作为参数传递吗

java - 如何在 UML 类图中表示方法内部的方法

java - java中用户定义包的访问方法

php - 如何使用 PHP 中的 Swiftmailer 库发送带有 STARTTLS 和自签名证书的邮件

security - 无需验证的 SSL 加密(类似于 SSH)

apache - 如何检测我的服务是使用 SSL 还是 TLS 以及哪个版本

java - 机器对机器 Java RMI 是否需要 Web 服务器?

java - Spring Batch - 无法初始化阅读器

java - 通过 servlet 生成动态复选框?