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

cod*_*oke 6 java ssl 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

没有设置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 7上的1.8.0_51都失败了.Windows安装是vanilla,而Linux安装已将urandom值更新为securerandom.source = file: /dev/./urandom.我不知道如何确定我的装置与Flo的不同之处.

cod*_*oke 5

HttpsURLConnection的默认和开箱即用的发送SNI IFF到它连接的是一个完全合格的名称对应的URL。它不会发送本地 Intranet 短名称别名的 SNI。

Extension server_name, server_name: [type=host_name (0), value=site.company.com]
Run Code Online (Sandbox Code Playgroud)

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