Java 7引入了默认情况下启用的SNI支持。我发现某些配置错误的服务器会在SSL握手中发送“无法识别的名称”警告,大多数客户端会忽略此警告… Java除外。如@Bob Kerns所述,Oracle工程师拒绝“修复”此错误/功能。
解决方法是,他们建议设置
jsse.enableSNIExtension属性。要允许您的程序无需重新编译即可运行,请按以下方式运行您的应用:
java -Djsse.enableSNIExtension=false yourClass
也可以在Java代码中设置该属性,但是必须在任何SSL操作之前设置该属性。加载SSL库后,您可以更改属性,但不会对SNI status产生任何影响。要在运行时禁用SNI(具有上述限制),请使用:
System.setProperty("jsse.enableSNIExtension", "false");设置此标志的缺点是SNI在应用程序中的所有位置都被禁用。为了利用SNI并仍然支持配置错误的服务器:
SSLSocket
使用您要连接的主机名创建一个。让我们命名为sslsock
。- 尝试运行
sslsock.startHandshake()
。这将阻塞直到完成或在错误时引发异常。每当中发生错误时startHandshake()
,请获取异常消息。如果等于handshake alert: unrecognized_name
,则说明服务器配置错误。 - 当您收到
unrecognized_name
警告时(在Java中是致命错误),请重试打开一个SSLSocket
,但是这次没有主机名。这有效地禁用了SNI(毕竟,SNI扩展名是关于在ClientHello
消息中添加主机名)。
对于Webscarab SSL
代理,此提交实现后备设置。



