基于 JSSE 示例,我尝试在服务器端获取 TLS 参数“服务器名称指示”(SNI) 的值 - 但没有成功。我确信该值是由客户端发送的,因为我使用了显示该值的网络嗅探器(Wireshark)。
但是当我使用以下代码片段时,服务器名称参数列表为空(同时显示“协议”):
public void connectionAccepted(Socket socket)
{
System.out.println("Connection accepted!");
try {
/* get SNI parameter */
SSLSocket sslSocket = (SSLSocket)socket;
SSLParameters sslParams = sslSocket.getSSLParameters();
List<SNIServerName> serverNames = sslParams.getServerNames();
for(SNIServerName item : serverNames){
System.out.println("SNI: " + item.toString());
}
String[] protocols = sslParams.getProtocols();
for(String item : protocols) {
System.out.println("Protocols: " + item.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
无论出于何种原因,Java SNI 实现显然不提供服务器端的实际主机名。相反,文档 [1](在“基于 SSLSocket 的虚拟服务器调度程序”下)建议手动解析初始 SSL 数据包并从中提取服务器名称。
您还可以使用 SNIMatcher [2] 来要求客户端提供特定名称;如果匹配器不匹配,则客户端会在 SSL 层收到错误。
[1] http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#SNIExamples
[2] http://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SNIMatcher.html
Update:我编写了一个自定义 SNI 解析器,它的工作原理如下:客户端将 SNI 作为 SSL ClientHello 消息的一部分发送,这是作为建立 SSL 连接的一部分发送的第一条消息。我的实现首先对其进行解析,然后使用与请求的主机名匹配的正确服务器端证书设置 SSLEngine。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)