我们有一个 Java 17 Quarkus 应用程序编译为本机可执行文件 (ubi-quarkus-native-image:22.2-java17),在 Kubernetes 中运行。它使用 SSL 连接到旧的集成服务器,发出 HTTP 请求。我们的应用程序使用套接字工厂创建 SSLSocket 并连接它;请求成功。完成后,我们调用 SSLSocket#close。这也有效,但在另一边他们记录了这个:
12:51:16 : ssl_debug(58): Shutting down SSL layer...
12:51:16 : ssl_debug(58): Sending alert: Alert Warning: close notify
12:51:16 : ssl_debug(58): Read 15328 bytes in 3 records, 15214 bytes net, 5071 average.
12:51:16 : ssl_debug(58): Wrote 175 bytes in 1 records, 152 bytes net, 152 average.
12:51:16 : ssl_debug(58): Closing transport...
12:51:16 : ssl_debug(58): Waiting on peer close notify...
12:51:16 : ssl_debug(58): Received alert message: Alert Warning: user canceled
12:51:16 : ssl_debug(58): Exception reading SSL message: iaik.security.ssl.SSLException: Peer sent alert: Alert Warning: user canceled
12:51:16 : ssl_debug(58): Closing transport...
12:51:16 : ssl_debug(58): Transport closed.
Run Code Online (Sandbox Code Playgroud)
据我所知,他们应该从我们这里得到一个密切的通知警报,我们也应该从他们那里得到一个密切的通知警报。不幸的是,我们这边发送了用户取消警报(代码 90)。这只是一个警告,但他们将其视为错误并丢弃整个请求,即使他们已经回答了。
我找到了一种方法来规避这个问题。如果我在关闭之前在套接字上调用 shutdownOutput ,则一切正常。然而,根据适当关闭 SSLSocket,这是错误的,它确实感觉像是一个肮脏的解决方法。
我无法让其他供应商修复其应用程序中的错误处理。有没有更好的方法来避免向用户发送取消警报?这是 SSL 实现中的错误,还是预期的错误?
在这两种情况下,套接字在关闭之前已被刷新,并且从其中读取(确保没有待处理的入站数据)没有任何区别。在关闭前等待一分钟也没有什么区别。
编辑:看起来其他服务器因解决方法而失败,并需要最终警报彻底关闭,所以解决这个问题真的很好。
编辑:这里的代码很简单,但我会根据要求添加它。
try (var socket = connect(url, httpChannel)) {
// Successfully make request here
// The workaround below fixes the problem
//socket.shutdownOutput();
} // close called on SSLSocket here
Run Code Online (Sandbox Code Playgroud)
connect 中的代码是(简化的):
var plainSocket = new Socket();
plainSocket.connect(new InetSocketAddress(hostName, port), (int) connectionTimeout.toMillis());
plainSocket.setSoTimeout((int) connectionTimeout.toMillis());
var secureSocket = (SSLSocket) getSocketFactory(keyManagers, trustManagers, sslContextProtocol).createSocket(plainSocket, hostName, port, true);
var params = secureSocket.getSSLParameters();
params.setEndpointIdentificationAlgorithm("HTTPS");
secureSocket.setSSLParameters(params); // Optional but usually on
secureSocket.setUseClientMode(true);
secureSocket.setSoTimeout((int) readTimeout.toMillis());
secureSocket.startHandshake(); // Optional, but usually on
return secureSocket;
Run Code Online (Sandbox Code Playgroud)
在另一端(我们充当服务器),我们执行 serverSocket#accept 并在 finally 块中调用关闭请求套接字,可选地首先使用类似的 socket#shutdownOutput 来解决问题。
| 归档时间: |
|
| 查看次数: |
283 次 |
| 最近记录: |