如何在不关闭底层套接字的情况下优雅地关闭Java SSL会话?
场景是Java客户端连接到(非Java)服务器,设置SSL并安全地将凭证(用户名和密码)发送到服务器.服务器设置在这些凭据下运行的环境,在此环境中生成一个新进程并将套接字句柄传递给它,但问题是这个新进程无法重用现有的SSL连接(并且无法使用SSL会话)恢复)…所以我们的想法是在生成新进程之前关闭SSL,然后使用新进程从头开始重新协商SSL会话.
问题是Java的SSLSocket’s close()方法除了关闭SSL会话之外还关闭套接字(到sending the close_notify alert).似乎没有相当于OpenSSL的SSL_shutdown()功能,它允许打开底层套接字.
>第二次使用SSLSocket.startHandshake(),但是会自动尝试恢复现有的缓存SSL会话(失败,因为生成的服务器进程不知道此会话),并且,虽然有一个方法到force resuming SSL sessions or die trying,但是没有方法可以使所有缓存的会话无效或禁用缓存会话的使用.
>使用SSLSocketFactory.createSocket()在现有套接字的顶部创建SSLSocket,并将autoClose设置为false.这不会阻止close()方法关闭底层套接字,我怀疑autoClose参数只会阻止套接字在初始握手失败时被关闭.
>在现有套接字上创建SSLSocket(如上所述),然后创建第二个SSLSocket,用于与生成的进程进行SSL握手(来自新的SSLContext).这会失败,因为当服务器发送close_notify警报时(在生成子进程之前),Java会关闭套接字.
我听说过SSLEngine,但我也读过(尽管源代码目前没有我),用TCP / IP编写正确的SSL实现是一件非常痛苦的事情,当我需要的时候看起来有些过分.是有一个SSLSocket版本,其close()不会调用super.Close().
但是,SSLSocket似乎甚至不会覆盖close()(根据javadoc),所以我不确定它是如何挂钩close()方法的时候似乎没有任何支持在Socket上注册关闭侦听器.
公司政策规定不能使用第三方加密库,因此我无法转向其他SSL实施,例如Bouncy Castle之前的解决方案.
如果我们无法使当前的1插槽设计工作,另一种方法是重写客户端和放大器.服务器使用2个独立的套接字(在必须反对拒绝服务和中间人攻击方面变得相当混乱,而不是SSL首先应该用于什么?).
任何有关如何解决这个问题的意见或想法都会受到欢迎.