在Java 8中,可以使用HttpsURLConnection来发送服务器名称指示(SNI)



Oracle 文档似乎表明 Java 8 默认自动发送 SNI。Wireshark表示不然。我是PowerShell系统管理员,而不是Java开发人员,所以几乎可以肯定我忽略了一些东西。

与正确的信任密钥库一起使用时,以下代码从不需要 SNI 的所有 SSL 网站返回状态 200。当连接到多主机 Apache 服务器的默认 SSL 网站时,它也会返回良好。但是,当系统要求连接到非默认站点时,由于证书名称与站点名称不匹配,它将失败,因为它连接到默认站点。

import java.util.*;
import java.net.*;
import javax.net.ssl.*;
import java.io.*;
public class testJavaHttpConn {
    public static void main(String[] args) throws Exception {
        String strUrl = args[0];
        System.out.println("Trying to connect to " + strUrl);
        try {
            URL url = new URL(strUrl);
            HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection();
            System.out.println("Connecting");
            urlConn.connect();
            System.out.println("Done");
            System.out.println("Response " + urlConn.getResponseCode());
        } catch (IOException e) {
            System.err.println("Error creating HTTP connection");
            e.printStackTrace();
            throw e;
        }
    }
}

我没有设置System.setProperty("jsse.enableSNIExtension","false"(;当我设置-Djavax.net.debug=ssl时,它清楚地显示未设置服务器名称扩展名。

我知道我可以实现SSLSocket并设置SSLParameter服务器名称,如果我愿意潜入下一个更深的抽象层,但我想避免这种情况。

编辑:代码按照上面注释中Flo的编写方式工作。Linux 1.8.0-194.11.3.el5 上的 1.8.0_72 和 Windows 7 上的 1.8.0_51 对我来说是失败的。Windows安装是原版的,而Linux安装已将urandom值更新为securerandom.source=file:/dev/./urandom。我不确定如何确定我的安装与 Flo 的有什么不同。

默认情况下,HttpsURLConnection 确实会发送 SNI,并且如果它连接的 URL 是完全限定的名称,则开箱即用。它不会为本地 Intranet 短名称别名发送 SNI。

Extension server_name, server_name: [type=host_name (0), value=site.company.com]

(作为记录,我还需要为短名称和完全限定的名称部署带有 SAN 的新证书,但这微不足道。

相关内容

最新更新