为什么使用TLSv1.2时SSLContext无法返回SSLSession信息?
问题原因
- 你遇到的情况并非配置遗漏,核心差异来自服务端的TLS实现:api.github.com的TLSv1.2握手阶段返回的会话标记为不可复用,也没有返回有效会话票据,SunJSSE默认不会将这类会话存入全局客户端会话上下文,因此你遍历
sslContext.getClientSessionContext()拿不到对应记录。你更换其他站点能正常打印,也印证了是服务端配置差异导致的问题。 - 次要影响因素是你使用的Apache HttpClient 4.3.2版本较老,存在部分会话缓存逻辑的已知缺陷,也可能加剧这个问题。
解决方案
方案1:直接从当前请求上下文拿会话(推荐)
不用遍历全局会话上下文,直接从当前请求的执行上下文获取本次连接的SSLSession,不受服务端会话缓存配置影响,修改代码如下:
// 新增请求上下文 HttpContext context = new BasicHttpContext(); // 执行请求时传入上下文 HttpResponse response = httpClient.execute(httpGet, context); // 从上下文获取SSLSession SSLSession sslSession = (SSLSession) context.getAttribute("http.socket.ssl-session"); // 直接打印即可 System.out.println("---------------------------"); System.out.println("TLS session information"); System.out.println("Client: " + sslSession.getPeerHost() + ":" + sslSession.getPeerPort()); System.out.println("\tProtocol: " + sslSession.getProtocol()); System.out.println("\tSessionID: " + byteArrayToHex(sslSession.getId())); System.out.println("\tCipherSuite: " + sslSession.getCipherSuite());
方案2:手动将会话存入全局上下文
如果你需要保持现有遍历全局上下文的逻辑,可以在拿到当前会话后手动存入:
sslContext.getClientSessionContext().putSession(sslSession);
可选优化
升级Apache HttpClient到4.5.x以上版本,修复旧版本的会话缓存相关bug,适配更多服务端的TLS实现。
内容的提问来源于stack exchange,提问作者João Pedro Schmitt
相关产品推荐
相关产品推荐

