You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java RMI启用SSL时遇ConnectionException等连接问题求助

解决Java RMI启用SSL时的连接异常问题

针对你遇到的连接被拒绝、未知主机、远程端点非JRMP服务器这三类问题,逐一排查代码中的关键错误并给出修正方案:

核心错误点分析

  1. 客户端未配置SSL SocketFactory:默认的LocateRegistry.getRegistry()使用普通JRMP协议连接,但你的RMI注册表和远程对象都绑定了SSL SocketFactory,导致客户端用非SSL连接SSL端口,触发“远程端点非JRMP服务器”异常。
  2. 客户端缺失SSL信任库配置:客户端未指定信任库,无法验证服务器证书,会导致连接失败或证书验证错误。
  3. 服务器端信任库配置错误:服务器错误加载了客户端信任库client.truststore,单向认证场景下服务器仅需配置自身密钥库,无需客户端信任库。
  4. 主机名解析问题: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属性。

测试步骤

  1. 先运行Register类启动服务器。
  2. 再运行App类启动客户端,观察是否成功调用loginUser()方法并输出true。

内容的提问来源于stack exchange,提问作者AlphabetsAlphabets

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 08:48:17