接前面内容,这里主要谈我们实现一开始描述的实际的技术需求的过程。
我们在建立与服务器的SonicMQ的SSL连接时,用了第三方jar去完成握手,而该第三方包采用的是标准的Java接口方式,即SSLContext.getInstance()。这也很容易理解,因为第三方jar的提供方并不能假设用户一定是在websphere环境下使用该第三方jar,所以采用标准方式更为可取。
我们的碰到的最大问题就是该jar在Oracle的jdk上可以工作,而在IBM的jdk都不能工作,出现SSLHandShake failure错误。开启-Djavax.net.debug=true后发现在第一步"ClientHello"时就出错了,因为write时采用了SSLv3协议,而recv得到则是TLSv1协议,故协议匹配失败,握手不成功。
多次研究后,终于发现问题出在Oralce的jdk和IBM的jdk对下面语句的处理是不一样的。Oracle的JDK会优先采用TLSv1和TLSv2去尝试握手连接,而IBM的JDK则直接采用SSLv3协议,而对方不支持SSLv3协议,故握手失败。
SSLContext.getInstance("SSL");
分析找出原因之后,就是怎么解决。两个选择:
- 一个是改第三方源码,把参数SSL改成TLS。一个参考可见:
- 另一个选择是更新IBM的JDK,因为IBM已经意识到这个问题并提供了fix patch。具体说明如下
http://www-01.ibm.com/support/docview.wss?uid=swg21687173
其描述的现象跟我们实际碰到的完全吻合,如下:
其提供了fix patch的安装,以解决这个问题。
http://www-01.ibm.com/support/docview.wss?uid=swg24038669
一个问题:既然IBM已经意识到这个接口的实现是有问题的,为什么不升级websphere的情况下大部分SSL连接不会有问题呢?
回答这个问题就要参考上一篇中提到两种使用方式,实际中大部分情况属于前一种,即通过websphere中的ssl配置来建立SSL连接,而不是直接跟IBM的JDK交互来建立SSL连接,要知道在SSL配置中协议项的默认值是TLS_SSL,表示优先选用TLS协议,所以大部分情况不会出错。而我们的使用方式属于另一种。