SSLProtocolException when using HttpsUrlConnection against same server from separate threads

时间:2018-06-04 17:38:22

标签: java httpsurlconnection

Been scratching my head for the best part of 2 days now. Any pointers or wild guesses are welcome at this point.

I have 2 separate webapps running in Tomcat 8.5 making client https connections to different urls at the same server (a Sales Force sandbox).

Whatever of them to get loaded first works alright but the second one fails on connect with

javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 5

The noted 5 above can be randomly 2, 4, 3 or 1. Also message can be Unknown record type...

There seems to be some kind of shared resource under the hood as both webapps work correctly on their own. Seems to me as if my client was trying to initiate a new handshake while the server is reusing a previously open connection??

Calling disconnect() on the connections does not make any difference and neither does sending a "Connect: close" header. Also tried consumption of all response data and closing streams without success.

Exception is always thrown at conn.getOutputStream().

Here's what one thread does:

final HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
conn.setRequestProperty("Content-Length", String.valueOf(reqBytes.length));
conn.setRequestProperty("Connection", "close");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
     os.write(reqBytes);
     os.flush();
}

final StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
     b.append(line).append(NEWLINE);
}
conn.disconnect();

Here's the other:

URL url = new URL(reportingUrl);
byte[] reqBytes = report.toString(2).getBytes("UTF-8");
final HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
 conn.setRequestMethod("POST");
 conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
 conn.setRequestProperty("Content-Length", String.valueOf(reqBytes.length));
 conn.setRequestProperty("Connection", "close");
 conn.setDoOutput(true);
 try (OutputStream os = conn.getOutputStream()) {
     os.write(reqBytes);
     os.flush();
 }
 InputStream in = conn.getInputStream();
 byte[] buffer = new byte[1024];
 while (in.read(buffer) > -1) {}
 conn.disconnect();

Finally here's some customization I'm doing at server start:

TrustManager[] tlsTrustManagers = new TrustManager[]{new ReloadableX509TrustManager(null, null)};
 SSLContext ctx = SSLContext.getInstance("TLSv1.1");
 ctx.init(null, tlsTrustManagers, null);
 ctx = SSLContext.getInstance("TLSv1.2");
 ctx.init(null, tlsTrustManagers, null);
 SSLContext.setDefault(ctx);

ReloadableX509TrustManager just imports any unknown certificate into de current truststore and reloads itself. I've been using it for years without issue. At any rate it only does something special each fist time ever it sees a new untrusted certificate.

Many thanks!

1 个答案:

答案 0 :(得分:0)

所以,回答这个问题,是的,这应该有效。它不是在我的旧jdk 8更新102中,但它肯定在版本8更新172中。

我真的不明白“只有第二个实例受影响的行为”,但它肯定与无效的无限强度政策文件有关。设置这些解决了这个问题。

现在这不是jdk 8 update 161以后的问题。

非常感谢