SSL连接重置

我正尝试连接到Java中的HTTPS端点。 我试过的每个方法(下面的更多细节)都会生成这个堆栈跟踪:

java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:168) at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293) at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:753) at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75) 

我努力了:

  • 连接javax SOAP库和一个新的URL(“https:// …”)
  • 连接新的URL(“https:// …”).openConnection()
  • 手工创buildSSL连接:

      Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) factory.createSocket("...", 443); Writer out = new OutputStreamWriter(socket.getOutputStream()); // https requires the full URL in the GET line // out.write("GET / HTTP/1.0\r\n"); out.write("\r\n"); out.flush(); // read response BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); int c; while ((c = in.read()) != -1) { System.out.write(c); } out.close(); in.close(); socket.close(); 

更多的细节:

  • 我尝试过的每种方法都与其他SSL服务器相悖,这就是这个特定的服务器(我无权讨论什么服务器,它是一个业务合作伙伴)
  • 我可以通过Web浏览器连接到这个服务器,并用curl假装SOAP请求。 这是Java特定的。

所以,似乎很清楚,Java和HTTPS服务器之间在握手过程中存在一些分歧,这可能意味着服务器有一些奇怪的SSLconfiguration。 但是,我没有直接访问服务器,而且所有的人都在世界的中途,所以沟通由于时区不同而有点紧张。

如果我的假设是正确的,那么可能存在哪些SSL问题? 什么可能会导致这样的事情? 我在哪里可以请求控制服务器的人寻找问题? 当我用curl执行请求时,我找回了这些服务器configuration头文件:

 Server: Apache/2.2.9 (Debian) mod_jk/1.2.26 PHP/5.2.6-1+lenny10 with Suhosin-Patch mod_ssl/2.2.9 OpenSSL/0.9.8g mod_perl/2.0.4 Perl/v5.10.0 X-Powered-By: PHP/5.2.6-1+lenny10 X-SOAP-Server: NuSOAP/0.7.3 (1.114) 

这是一个SSL版本问题。 服务器仅支持SSLv3,Java将从v2开始,并尝试向上协商,但并非所有服务器都支持这种类型的协商。

强制java只使用SSLv3是我意识到的唯一解决方案。

编辑,有两种方法可以做到这一点,我知道:

  • 如果您正在手动创建套接字,则可以设置已启用的协议

    socket.setEnabledProtocols(new String [] {“SSLv3”});

  • 如果您正在使用更高级别的库,则可能需要将所有SSL请求设置为仅使用v3,这是使用“https.protocols”系统属性完成的:

    java -Dhttps.protocols = SSLv3