SSL Session Management with JSSE SSLEngine
我正在使用NIO和SSLEngine在SSL Web服务器上工作。我能够成功处理握手并发送/接收应用程序数据。但是,我很难理解如何维护SSL会话状态。
我正在使用Firefox 10测试我的Web服务器。在初始页面加载时,一切正常。握手成功完成。服务器处理客户端请求并发送回响应。响应清晰可见,浏览器加载应用程序数据(html,图像等)。这是从客户端发送到服务器的消息的快照。
页面请求#1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | =============================================== == Message 1 =============================================== Client Request: handshake (22) - client_hello (1) Server Response: handshake (22) - server_hello (2) - certificate (11) - server_key_exchange (12) - certificate_request (13) - server_hello_done (14) =============================================== == Message 2 =============================================== Client Request: handshake (22) - certificate (11) - client_key_exchange (16) change_cipher_spec (20) - client_hello (1) handshake (22) *** Encrypted Message **** =============================================== == Message 3 =============================================== Client Request: application_data (23) *** Encrypted Message **** application_data (23) *** Encrypted Message **** Server Response: application_data (23) *** Encrypted Message **** |
同样,在初始页面加载时,一切都很好。但是,如果刷新浏览器或转到另一个"页面",Firefox将发送应用程序记录,而不是客户端问候。
页面请求2
1 2 3 4 5 6 | =============================================== == Application Data =============================================== Client Request: application_data (23) *** Encrypted Message **** |
在这种情况下,SSLEngine尝试解包应用程序数据时将引发异常。
1 | javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? |
我相信这是因为我在每个页面请求中都实例化了一个新的SSLEngine。如果仅一次实例化SSLEngine并将其设置为全局/静态变量,则它会成功取消包装应用程序记录,并且可以将响应发送回客户端。我可以刷新页面,访问其他页面等,而没有任何问题。页面加载非常快,因为我们跳过了整个ssl握手过程。
不幸的是,如果我在其他所有浏览器(例如IE或Safari)上从其他浏览器访问网络服务器,则SSLEngine内部的会话状态就会崩溃,并且我的网络服务器无法响应任何新的SSL请求。因此,一次实例化SSLEngine并使它成为全局可访问的静态变量似乎不是一个可行的选择。所以...
我到底应该如何响应第二个页面请求(页面请求2)?除了IP地址之外,是否有其他方法可以将第二个页面请求(页面请求#2)绑定到初始握手请求(页面请求#1)?在第二个页面请求(页面请求#2)的应用程序数据中是否埋有SSL会话ID?
提前致谢!
您必须为每个