【问题标题】:Java TLS Session Reuse after closed connection关闭连接后的 Java TLS 会话重用
【发布时间】:2016-05-25 00:12:18
【问题描述】:

我有一个 Java TLS 客户端,它可以向服务器发送一系列请求,每个请求后跟对服务器的响应。

但是,有许多不同的服务器。有些是“多消息”服务器,在第一个请求后保持连接打开,以便可以通过第一个连接发送后续请求。其他是“单消息”服务器,在每条消息后关闭连接,因此后续消息需要新连接。客户端没有先验方法知道它正在与哪种类型的服务器通信,也无法修复服务器。

非常希望单消息服务能够在没有完全握手的情况下恢复会话。

我的原始客户端代码只是尝试通过同一连接发送后续请求。如果失败了,它只是打开了一个到服务器的新连接。因此,它可以同时处理单消息和多消息服务器。

但是,将第二条消息发送到单消息服务器时失败似乎会终止会话恢复。

我的肮脏工作是注意消息是否失败,然后假设它正在与单消息服务器通信,在这种情况下,客户端会在收到每个响应后显式关闭套接字。这使后续连接能够恢复会话。

但必须有更好的方法。不出所料,测试 isInputShutdown 或 isConnected 没有帮助,因为存在时间问题。单消息服务器的连接失败实际上发生在读取响应期间,写入请求之后,可能是由于缓冲。

有什么非常感谢的想法吗?

【问题讨论】:

    标签: java ssl


    【解决方案1】:

    在明文情况下你的初始解决方案是正确的:发送第二条消息时你会得到一个IOException: connection reset by peer,你可以通过重新连接来恢复。

    但是在 TLS 情况下它不起作用,因为由于致命的 TLS unexpected_message 警报,您不会收到 IOException: connection reset by peer 而是 SocketExceptionRFC 2246 #7.2 状态:

    具有致命结果级别的警报消息 在连接的立即终止。在这种情况下,其他 与会话对应的连接可能会继续,但 会话标识符必须无效,防止会话失败 被用来建立新的连接。

    [我的重点],因为失败的会话现在被认为是不安全的,并且

    unexpected_message

    收到了不适当的消息。此警报总是致命的 并且不应该在适当的通信中被观察到 实现。

    您的第二个解决方案似乎适合我。

    注意:

    • isInputShutdown() 永远不可能是真的,因为你不能在 SSLSocket 上调用 shutdownInput()
    • 一旦连接了套接字,isConnected() 将永远不会为假。
    • 两者都告诉您套接字的状态,而不是连接的状态,因此即使尝试它们也是徒劳的。这与“时间问题”无关。

    【讨论】:

    • 感谢您的确认。我认为不需要使会话无效,但事实就是如此。
    猜你喜欢
    • 2011-06-10
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 2018-04-09
    • 2015-07-21
    • 1970-01-01
    • 2017-12-01
    相关资源
    最近更新 更多