java - 从不同线程对同一服务器使用 HttpsUrlConnection 时出现 SSLProtocolException
问题描述
2 天来的大部分时间里,我一直在挠头。在这一点上,欢迎任何指针或疯狂的猜测。
我在 Tomcat 8.5 中运行了 2 个单独的 web 应用程序,使客户端 https 连接到同一服务器上的不同 url(销售人员沙箱)。
无论它们中的哪一个首先加载都可以,但第二个在连接时失败
javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 5
上面提到5
的可以是随机2
的4
、3
或1
。也可以留言Unknown record type...
引擎盖下似乎有某种共享资源,因为两个 web 应用程序都可以自己正常工作。在我看来,就好像我的客户端在服务器重用以前打开的连接时尝试启动新的握手?
调用disconnect()
连接没有任何区别,发送"Connect: close"
标头也没有。还尝试使用所有响应数据并关闭流但没有成功。
异常总是在conn.getOutputStream()
.
这是一个线程的作用:
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();
这是另一个:
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();
最后,这是我在服务器启动时进行的一些自定义:
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
只需将任何未知证书导入当前信任库并重新加载即可。我多年来一直在使用它,没有任何问题。无论如何,它只会在每次看到新的不受信任的证书时做一些特别的事情。
非常感谢!
解决方案
所以,要回答这个问题,是的,这应该有效。它在我的旧 jdk 8 update 102 中没有,但在版本 8 update 172 中确实如此。
我不太了解“只有第二个实例影响的行为”,但它肯定与不存在的无限强度策略文件有关。设置这些解决了这个问题。
现在这不是问题,因为jdk 8 update 161。
不管怎么说,还是要谢谢你
推荐阅读
- python - Pycharm 无法识别 pyodbc
- r - 有没有办法从具有缺失值的每小时数据中找到每日最大值
- image-processing - ffmpeg调整大图像和高分辨率
- swift - 如何在另一个函数中引用自定义 UITableView 单元格(Swift)
- java - 待定意图不运行服务
- c# - Xamarin Forms UWP 中的领域 2 路绑定引发异常
- nginx - Certbot,Niginx 如何将 3 个域链接到 1 个网站还为所有人启用 https
- python - 是否可以写在同一行而不写多行?
- c# - c# winform exe 与另一个 c# winform 通信 - 比如 COM
- python - 尝试使用 Python 3.6 安装 pyjinius 时未找到与 pyjinius 匹配的发行版