【发布时间】:2014-09-08 13:58:08
【问题描述】:
我有一段 Java 代码(实际上是一个 servlet)需要与之安全通信:
- 另一个 java 进程,通过 RMI,进行安全的远程方法调用和
- Google GCM 服务器,向移动设备发送通知。
这是安全绑定到远程对象的代码:
// 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 套接字工厂,但不能同时使用两者。如果我先连接到 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 ...
你能指点我正确的方向吗?
谢谢
【问题讨论】:
-
您看到了什么错误?堆栈跟踪会很有用。
-
抱歉,我编辑了问题并添加了堆栈跟踪
-
在第二种情况下,您真的在 getRegistry() 调用之前立即执行 setProperty() 调用吗?如果没有,您能否检查一下 Google 代码是否与 truststore 属性混淆了?
-
是的,对 setProperty() 的调用是在 getRegistry() 之前立即完成的,因为它们出现在我发布的代码中。为了安全起见,在第二种情况下,我在连接到 Google 服务器之前和之后打印了系统属性,但没有任何变化。
标签: java ssl rmi google-cloud-messaging