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

问题描述:

Oracle文档似乎表明Java 8自动默认发送SNI。 Wireshark表示否则。我是PowerShell系统管理员,而不是Java开发人员,所以我几乎可以肯定我忽略了一些东西。在Java 8中,可以通过HttpsURLConnection发送服务器名称指示(SNI)

与适当的信任密钥库一起使用时,以下代码将从不需要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”, “假”);当我设置-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的不同。

+0

所以你要找之外的其他方法[记录在这里](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#SNIExtension)? –

+0

我受到无知的限制。使用SSLSocket的代码片段假定知识构建前后的所有内容,但我缺乏这方面的知识。我还没有找到一个例子显示如何使用SSLSocket执行连接和检索,并将输出转换为HttpURLConnection返回的同一个对象。我已经根据这些片段构建了所有这些对象,但是一旦我拥有了它们,就无法对它们进行任何操作。鉴于我的无知,询问我是否忽略了导致HttpsURLConnection发送SNI的某个简单属性似乎是明智之举。如果答案是否定的,那么就是SSLSocket。 – codepoke

+1

我使用“https://sni.velox.ch”测试了您的代码,并且调试时显示“Extension server_name,server_name:[type = host_name(0),value = sni.velox.ch]'。它导致状态200.使用'System.setProperty(“jsse.enableSNIExtension”,“false”)'我得到一个错误(按预期)并且调试中缺少扩展。系统:Ubuntu Linux,Java 1.8.0_72(但也使用1.7.0_95)。可悲的是,我没有为你解决问题。 – flo

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

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

(根据记录,我还需要部署处理SAN短期和完全合格的名字一个新的证书,但是这是微不足道的。)