在Java8中可以使HttpsURLConnection发送服务器名称指示(SNI)

In Java 8 can HttpsURLConnection be made to send server name indication (SNI)

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

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

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 serverName,如果我愿意深入到下一个更深的抽象层,但我想避免这种情况。

编辑:代码的工作方式与上面在评论中为 Flo 编写的一样。我在 Linux 2.6.18-194.11.3.el5 上使用 1.8.0_72 并且在 Windows 上使用 1.8.0_51 失败 7. Windows安装是普通的,而 Linux 安装已将 urandom 值更新为 securerandom.source=file:/dev/./urandom。我不确定如何确定我的安装与 Flo 的不同。

HttpsURL连接确实默认发送SNI并且开箱即用iff​​ URL到它连接的是一个完全限定的名称。它不会发送本地 Intranet 短名称别名的 SNI。

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

(根据记录,我还需要为短名称和完全限定名称部署一个带有 SAN 的新证书,但这很简单。)