Java RMI启用SSL时遇ConnectionException等连接问题求助
解决Java RMI启用SSL时的连接异常问题
针对你遇到的连接被拒绝、未知主机、远程端点非JRMP服务器这三类问题,逐一排查代码中的关键错误并给出修正方案:
核心错误点分析
- 客户端未配置SSL SocketFactory:默认的
LocateRegistry.getRegistry()使用普通JRMP协议连接,但你的RMI注册表和远程对象都绑定了SSL SocketFactory,导致客户端用非SSL连接SSL端口,触发“远程端点非JRMP服务器”异常。 - 客户端缺失SSL信任库配置:客户端未指定信任库,无法验证服务器证书,会导致连接失败或证书验证错误。
- 服务器端信任库配置错误:服务器错误加载了客户端信任库
client.truststore,单向认证场景下服务器仅需配置自身密钥库,无需客户端信任库。 - 主机名解析问题:
InetAddress.getLocalHost().getHostName()可能返回无法被客户端解析的主机名,导致“未知主机”错误。
分步修正方案
1. 修正客户端代码(App.java)
添加SSL信任库配置,并使用SslRMIClientSocketFactory获取Registry:
package dcoms; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import javax.rmi.ssl.SslRMIClientSocketFactory; import dcoms.remote.RemoteInterface; public class App { public static void main(String[] args) { System.out.println("Starting"); try { // 配置客户端SSL信任库 System.setProperty("javax.net.ssl.trustStore", "client.truststore"); System.setProperty("javax.net.ssl.trustStorePassword", "123123"); // 使用SSL SocketFactory获取Registry,直接指定服务器IP避免解析错误 Registry registry = LocateRegistry.getRegistry("10.101.37.128", 9999, new SslRMIClientSocketFactory()); RemoteInterface obj = (RemoteInterface) registry.lookup("OrderSystem"); System.out.println(obj.loginUser()); } catch (Exception e) { e.printStackTrace(); } System.out.println("Ended"); } }
2. 修正服务器端注册代码(Register.java)
移除错误的客户端信任库配置,仅保留服务器密钥库:
import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; public class Register { public static void main(String[] args) throws Exception { int port = 9999; // 仅配置服务器自身密钥库 System.setProperty("javax.net.ssl.keyStore", "server.keystore"); System.setProperty("javax.net.ssl.keyStorePassword", "123123"); Registry reg = LocateRegistry.createRegistry(port, new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory()); Server server = new Server(); reg.rebind("OrderSystem", server); System.out.println("Server running"); } }
- 单向认证场景下,服务器无需配置
trustStore,除非需要验证客户端证书(双向认证)。
3. 验证密钥库文件路径
确保server.keystore和client.truststore文件位于程序运行的当前工作目录下,或者使用绝对路径指定,比如:
System.setProperty("javax.net.ssl.keyStore", "/opt/rmi/server.keystore");
4. 环境验证
- 确认服务器和客户端的密钥库密码与代码中设置的
123123一致。 - 关闭服务器和客户端所在机器的防火墙,或开放9999端口的入站/出站规则。
- 若需双向认证,需额外为客户端生成密钥库,并将客户端证书导入服务器信任库,同时客户端配置
keyStore属性。
测试步骤
- 先运行
Register类启动服务器。 - 再运行
App类启动客户端,观察是否成功调用loginUser()方法并输出true。
内容的提问来源于stack exchange,提问作者AlphabetsAlphabets
相关产品推荐
相关产品推荐

