最近一家供应商升级了他们的 XML SOAP Web 服务,放弃了对 TLSv1 的支持,这导致我们对他们的调用停止工作。
我稍微升级了我们的遗留 Java Spring 应用程序以尝试重新启用该功能。我有以下代码;
public boolean searchViaWS(....) throws Exception {
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(MessageFactory.newInstance());
messageFactory.setSoapVersion(SoapVersion.SOAP_11);
XmlBeansMarshaller marshaller = new XmlBeansMarshaller();
// THESE TWO LINES ARE NEW TO SUPPORT TLSv1.1
HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender(); // NEW
sender.setSslProtocol("TLSv1.1"); // NEW
NSCHWebServiceClient webServiceClient = new NSCHWebServiceClient(messageFactory);
webServiceClient.setMessageSender(sender); // NEW ALSO
webServiceClient.setMarshaller(marshaller);
webServiceClient.setUnmarshaller(marshaller);
return webServiceClient.searchViaWS(....);
}
所有 webServiceClient 所做的就是基于 wsdl 构建对象并调用 WebServiceTemplate.marshalSendAndReceive。
现在,我可以通过 Eclipse 中的单元测试来练习这段代码。
- 如果没有上面的新行,测试将失败并出现 ssl 握手异常,表示远程主机关闭了连接,假设是因为它们不再允许 TLSv1。
- 通过上面的新行,测试通过,从远程服务器获得成功响应。因此,我认为只需将协议(protocol)设置为 TLSv1.1 即可。
在 Eclipse 中,类路径表明它正在使用 JavaSE-1.6(由 jdk1.7.0_21 提供)
然而,当我将代码上传到我的服务器时,该服务器运行 Apache,使用 ajp 重定向到运行 Java 1.6.0_0 的 CentOS 机器上的 Tomcat 6.0.29,并执行相同的代码,ssl 握手异常继续。
该项目及其服务器非常古老,即使在最好的时候我也不能完全理解传输协议(protocol)。我是否正确地怀疑服务器上的 Tomcat 和/或 Apache 忽略了 Java 代码使用 TLSv1.1 的请求,因此仍在使用 TLSv1 并导致与远程服务器的握手错误?
最佳答案
终于找到解决办法了。正如我所怀疑的,Tomcat 导致了问题。 我在服务器上升级到Java 7,然后将以下内容添加到tomcat bin目录下的catalina.sh中;
JAVA_OPTS="$JAVA_OPTS -Dhttps.protocols=TLSv1.1,TLSv1.2"
关于Java Spring WS 客户端 - tomcat 或 apache 干扰?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38776828/