所以,我正在滚动我自己的基于 Java 的应用程序服务器(因为 Glassfish 等人不适用于非基于 Web 的应用程序),当然,加密是绝对必须的。因此,我使用标准编写了一个基本的 ssl 解决方案SslRMIClientSocketFactory
,和SSLRMIServerSocketFactory
. 到目前为止,一切都很好。不过,我还有一些其他问题,例如允许但不要求使用客户端证书(就像您 ssh 进入系统时一样),但我愿意考虑改天再做一次练习。
然而,在此过程中,我注意到自 2005 年左右以来随着“Java 5.0”的出现,我们显然对使用xinetd
基于 'nix 的解决方案有所帮助。在我看来,这样做的“新”帮助是能够从较低级别(如 xinetd - via )“继承”套接字信息System.inheritedChannel
。
我想我需要一个在 RMI 解决方案中一起使用加密和 xinetd 的示例,并在这里找到了一篇很棒的文章 The New RMI - 或者,至少,如果不是应该附带的示例代码,那就太好了文章不见了。有点烂,我猜。(有人有副本吗?!)文章中可见的示例太不完整,文本依赖于您拥有示例代码的事实。那好吧。简单地说,我不太明白 - 使用System.inheritedChannel
显然不像将其插入现有的 RMI Registry 相关代码那么简单 - 你显然必须创建一个套接字工厂,或者我只是不明白 - 因此,寻找一个例子。
于是我去打猎。我发现 Apache 的人做了类似的事情,这里描述了RMI Service Exporter,但是,它使用了我宁愿避免使用的技术 - SpringBeans,如果你愿意的话。而且,因为这是一个重要的例子,坦率地说,我对如何在我的工作中使用这种类型的解决方案有点迷茫。
我一直在寻找并发现乍一看似乎是一个名为InitializeRegistry的出色解决方案,但它根本没有对 SSL 的任何引用,我马上就迷路了。例如,它将自己描述为:
创建和导出一个注册表(使用继承的通道,如果有的话,如下所示),并将指定的名称绑定到该注册表中的指定代理。
我的问题是语言。特别是,我没有使用代理,即使我使用了,我也不知道为什么这很重要。而且我认为我将对象绑定到 RMI 注册表,而不仅仅是名称。也许如果有人可以澄清他们在做什么,这是一个很好的例子......
最后,我在 StackOverflow 上偶然发现了一个很棒的回复——这是有史以来最糟糕的回复之一,谈论Java RMI、SSL 和压缩。压缩不符合我的需求,但它是一个有启发性的讨论。不过,我看不出它如何帮助我理解如何同时将 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()
”——两者中的第二个。
删除 final.accept()
会导致错误倒计时,只是无法createSocket()
从此代码的静态上下文中使用“非静态方法”。但是当我尝试从类中删除“静态”时,它到处都是,无法使用无处不在的“ this
”引用。OTOH,我不知道如何制作SSLSocketFactory.createSocket()
静态!
...是否可以安全地假设accept()
用于访问传递的套接字 (!!) 的那个就足够了,并且不需要我尝试包含的后续一个?嗯……
我很乐意尝试一下,看看我能不能把它建成。
顺便说一句,我想我会setUseClientMode(false)
在以后使用......是吗?
进一步思考......
我意识到这可能InitializeRegistry.java
是一个糟糕的起点,并回到“第一原则”,发现当它第一次接受channel
它时,它可能会误入歧途System.inheritedChannel
,并将其转换为 a ServerSocket
,所以覆盖的想法ServerSocketFactory
是,嗯,“很多工作”。然后它就撞到了我:
这里的重点是尝试确保未经请求的连接请求到达正在侦听的目标。但更重要的是,注册表中必须有一个对象才能使用它,为此,人们也需要任何创造这种情况的东西。因此,确保创建对象的代码作为 SYSTEM SERVICE 运行,而不用担心将其作为 NETWORK SERVICE 来解决,这同样好,也更容易。
因此,我在下注。...不过,删除这个问题似乎很可惜,因为这可能会为其他人提供指导——这是 StackOverflow 中唯一一个涉及这个主题的查询。
再次感谢。