SSLEngine documentation指示如何正确关闭SSL连接。更具体地说,它提供了有关如何处理断开连接的说明:


  除了有序关闭之外,还可能存在无序关闭,其中在交换关闭消息之前先切断传输链路。在前面的示例中,当尝试读取或写入非阻塞SocketChannel时,应用程序可能会获得-1。当您到达输入数据的末尾时,应调用engine.closeInbound(),它将使用SSLEngine验证远程对等方已从SSL / TLS角度完全关闭,然后应用程序仍应尝试完全关闭通过使用上述过程。


基本上,如果链接断开,则应调用engine.closeInbound()。但是,此closeInbound()方法的文档表明,如果在从对等方收到正确的关闭消息之前调用了它,它将引发异常。在我看来,如果断开连接,将永远不会收到此close_notify消息,因此此方法将始终抛出该异常。

我进行了测试,做了一个简单的关闭过程,其中socketChannel.read()返回-1,我调用engine.closeInbound(),并且确实得到以下异常:

javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?


我想念什么?文档的这两个部分不是矛盾的吗?

最佳答案

我认为文档的这两部分并不矛盾。


  当您到达输入数据的末尾时,应调用engine.closeInbound()


这适用于完全关闭和断开的连接。在断开连接时,将引发异常(即,如果在收到close_notify之前调用了该异常)。
如果收到close_notify(或者甚至根本没有启动连接),则不会引发此异常。

我不太确定您如何进行简单的关机测试,但是您应该首先从另一端发送close_notify(例如,使用closeOutbound())。在这种情况下,您不应该在获得socketChannel.read()之前从close_notify收到-1(这样您就不会获得异常)。

(只要有兴趣,不久前会有一个similar question on SSLSocket。)

07-24 09:39
查看更多