Java上的服务器名称指示(SNI)

Java上的服务器名称指示(SNI),java,http,ssl,sni,Java,Http,Ssl,Sni,有人能帮我开始用Java实现带有服务器名称指示的HTTP连接吗 我正在尝试从我管理的站点请求内容。我一直在使用Apache的HttpClient库,但是我对安全内容的请求失败了,因为该网站只对HTTPS使用SNI,并且在DefaultHttpClient中没有启用SNI。我已经在Apache的HttpClient库中寻找了关于如何实现这一点的说明,但我看到最后的文档是:,它已经过时了(参考了HttpClient和HttpCore是Apache commons包一部分时的代码) 所以。。。有什么帮

有人能帮我开始用Java实现带有服务器名称指示的HTTP连接吗

我正在尝试从我管理的站点请求内容。我一直在使用Apache的HttpClient库,但是我对安全内容的请求失败了,因为该网站只对HTTPS使用SNI,并且在DefaultHttpClient中没有启用SNI。我已经在Apache的HttpClient库中寻找了关于如何实现这一点的说明,但我看到最后的文档是:,它已经过时了(参考了HttpClient和HttpCore是Apache commons包一部分时的代码)


所以。。。有什么帮助吗?

似乎此问题已在中修复。

您可能需要跟踪

Java 7的底层客户端实现能够支持它,并通过SSLSocketImpl#setHost(由sun.net.www.protocol.https.HttpsClient调用)公开该功能

关于Java7的使用

    new URL("https://cmbntr.sni.velox.ch/").openStream()

直到HTTPCLIENT-1119通过以下所述的短修复程序修复为止:
可以将SNI服务器支持添加到JDK 7,并在中与X509ExtendedKeyManager一起使用。

对我有效的方法是在Apache配置中正确配置
ServerName

/etc/apache2/sites available/default

<VirtualHost *:443>
  ServerName foo.domain.com
  ...
</VirtualHost>

ServerName foo.domain.com
...

如中所述。

这是我在org.apache.httpcomponents的httpclient v4.3+中所做的

private HttpClientConnectionManager createConnectionManager(final SSLContext ctx) {
    LOG.info("Creating sslConnectionSocketFactory");
    final SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(ctx) {

        @Override
        protected void prepareSocket(SSLSocket socket) throws IOException {
            try {
                System.out.println("************ setting socket HOST property *************");
                PropertyUtils.setProperty(socket, HOST, Constants.SNI_HOST);
            } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
                LOG.error(ex.getMessage());
            }
            super.prepareSocket(socket); 
        }

    };

    LOG.info("Creating connectionRegistry");
    final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("https", sslSF)
            .build();

    LOG.info("Creating poolingConnectionManager");
    final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
    connectionManager.setDefaultMaxPerRoute(MAX_CONNECTIONS_PER_ROUTE);
    connectionManager.setMaxTotal(MAX_CONNECTIONS);

    return connectionManager;
}

谢谢。我明白了。但是,RFC没有给我任何关于如何实现这一点的提示(除了从头开始构建我自己的客户端)。有没有关于现有工具的想法,或者如何使用Apache HttpClient来实现这一点的想法?它现在已经修复,在HttpComponents HttpClient 4.3.2中提供。在OpenJDK上的Tomcat中使用HttpClient 4.3.2(直到版本
1.7.0\u 111
),SNI仍然会失败。在切换到Oracle热点(
1.7.0\u 80
)之后对于任何在AWS Beanstalk上遇到这种情况的人,请查看此eExtension以将JVM切换到Oracle:请不要使用
SSLConnectionSocketFactory。允许所有主机名\u验证器
。对于像我一样好奇的人,请澄清:
PropertyUtils
来自
commons beanutils
String HOST=“HOST”;
常量。SNI_HOST
是要连接到的服务器的DNS主机名。最重要的是:httpclient 4.5不再需要自定义工厂。2@DaanReid-你所说的“不再需要定制工厂”是什么意思?是否有我们可以使用的默认实现。@Shyam如果您的httpclient是最新的,则默认实现是开箱即用的:
SSLConnectionSocketFactory connectionSocketFactory=new SSLConnectionSocketFactory(sslContext)
SNI在Java7中工作,但是……请注意,可能有人禁用了它。您可能希望搜索
jsse.enableSNIExtension
。并检查是否有人将其设置为false
final KeyManager[] keyManagers = createKeyManagers();
final TrustManager[] trustManagers = createTrustManagers();
final SSLContext ctx = createSslContext(keyManagers, trustManagers);

final HttpClientConnectionManager connectionManager = createConnectionManager(ctx);

LOG.info("Creating httpClient");
HttpClient httpClient = HttpClients
        .custom()
        .setConnectionManager(connectionManager)
        .build();