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
。)