设置多个SSL Socket工厂

时间:2014-09-08 13:58:08

标签: java ssl rmi google-cloud-messaging

我有一段需要与以下内容安全通信的Java代码(实际上是一个servlet):

  1. 另一个java进程,通过RMI,进行安全的远程方法调用和
  2. Google GCM Servers,用于向移动设备发送通知。
  3. 以下是安全地绑定到远程对象的代码片段:

        // let's set some system properties needed for RMI on SSL
        Properties sysProps = System.getProperties();
        sysProps.setProperty("javax.net.ssl.keyStore", ...);
        sysProps.setProperty("javax.net.ssl.keyStorePassword", ...);
        sysProps.setProperty("javax.net.ssl.trustStore", ...);
        sysProps.setProperty("javax.net.ssl.trustStorePassword", ...);
    
        try {
            String registryHost = ...;
            int registryPort = ...;
    
            Registry registry = LocateRegistry.getRegistry(registryHost, registryPort, new SslRMIClientSocketFactory());
            MyRemoteObject obj = (MyRemoteObject) registry.lookup(...);
        } catch (Exception e) {
            log.error("RMI Exception",e);
        } 
    

    然后,为了连接到Google GCM服务器,我提供了Google提供的唯一代码以及我读过的任何教程:

        config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
        config.setSecurityMode(SecurityMode.enabled);
        config.setReconnectionAllowed(true);
        config.setRosterLoadedAtLogin(false);
        config.setSendPresence(false);
        config.setSocketFactory(SSLSocketFactory.getDefault());
    
        // NOTE: Set to true to launch a window with information about packets
        // sent and received
        config.setDebuggerEnabled(true);
    
        // -Dsmack.debugEnabled=true
        XMPPConnection.DEBUG_ENABLED = false;
    
        connection = new XMPPConnection(config);
        connection.connect();
    

    我可以让其中一段代码同时工作,但我无法同时建立两个安全连接。我可以使用默认的SSLSocketFactory或设置RMI SSL Socket工厂,但不能同时使用两者。如果我首先连接到RMI服务器,当我尝试连接到Google GCM服务器时出现以下错误:

    2014-09-08 16:14:05,172 ERROR [pool-4-thread-1] (GcmManager.java:109) - Problems connecting with Google XMPP servers
    Connection failed. No response from server.: 
    at org.jivesoftware.smack.PacketReader.startup(PacketReader.java:121)
    at org.jivesoftware.smack.XMPPConnection.initConnection(XMPPConnection.java:636)
    at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection.java:596)
    at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1010)
    at com.tigratelecom.server.callback.web.notification.GcmManager.connect(GcmManager.java:171)
    at com.tigratelecom.server.callback.web.notification.GcmManager.sendNotification(GcmManager.java:107)
    at com.tigratelecom.server.callback.web.notification.NotificationSender.sendNotifications(NotificationSender.java:24)
    at com.tigratelecom.server.callback.web.servlet.CallbackServlet$1.run(CallbackServlet.java:107)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)
    

    如果我先连接到Google服务器,那么一切顺利,直到我尝试连接到RMI服务器,但失败并出现以下错误:

    java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:304)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
    at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:340)
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at ...
    

    请您指出我正确的方向吗?

    由于

1 个答案:

答案 0 :(得分:0)

我继续摆弄这个问题,直到找到了什么。我假设连接到Google GCM服务器(来自Smack库)的代码,因为它使用了默认的SSLSocketFactory,使用了默认的java信任库中已经存在的一些证书,可以在jre / lib / security / cacerts中找到在java SDK安装中。由于我必须创建自己的信任库和密钥库来设置RmiSSLSocketFactory,我认为Smack库代码无法找到它需要的任何证书。

所以我决定将cacerts中的所有证书导入到我自己的密钥库中。为此,我跑了:

keytool -importkeystore -srckeystore "c:\Program Files\Java\jdk1.7.0_25\jre\lib\security\cacerts" -destkeystore my_truststore  -srcstorepass changeit -deststorepass mypass

之后,一切顺利,两个安全连接都没有问题。

我希望将来可以帮助某人。