我有一段需要与以下内容安全通信的Java代码(实际上是一个servlet):
以下是安全地绑定到远程对象的代码片段:
// 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 ...
请您指出我正确的方向吗?
由于
答案 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
之后,一切顺利,两个安全连接都没有问题。
我希望将来可以帮助某人。