Почесал мою голову лучшую часть двух дней.На этом этапе приветствуются любые указатели или догадки.
У меня есть два отдельных веб-приложения, работающих в Tomcat 8.5, которые устанавливают клиентские соединения https на разные URL-адреса на одном сервере (в изолированной программной среде Sales Force).
Независимо от того, кто из них загружается, первый работает нормально, но второй не работает при соединении с
javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 5
. Указанные выше значения 5
могут быть случайным образом 2
, 4
, 3
или 1
,Также сообщением может быть Unknown record type...
Кажется, что под капотом находится какой-то общий ресурс, поскольку оба веб-приложения работают правильно самостоятельно.Мне кажется, что мой клиент пытался инициировать новое рукопожатие, пока сервер повторно использует ранее открытое соединение ??
Вызов 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
просто импортирует любой неизвестный сертификат в текущее хранилище доверенных сертификатов и перезагружает себя.Я использую его годами без проблем.Во всяком случае, он делает что-то особенное каждый раз, когда видит новый ненадежный сертификат.
Большое спасибо!