英文:
Apache HIVE JDBC: How to customize SSL certificate validation?
问题
我想知道如何在Java中为Apache HIVE JDBC驱动程序自定义SSL证书验证。这包括启用使用自签名证书以及忽略其他验证错误。
以下是抛出错误的代码:
// 使用库 hive-jdbc-3.1.2-standalone.jar
Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection con = DriverManager.getConnection("jdbc:hive2://somethingsomethinghere.azurehdinsight.net:443/default;transportMode=http;ssl=true;httpPath=/hive2", "user@somedomain.com", "ultra-secure password");
如果代码能够工作,将建立与HIVE的连接,并相应地设置con
。然而,我收到以下错误:
java.sql.SQLException: 无法通过JDBC Uri打开客户端传输:jdbc:hive2://somethingsomethinghere.azurehdinsight.net:443/default;transportMode=http;ssl=true;httpPath=/hive2:无法建立与jdbc:hive2://somethingsomethinghere.azurehdinsight.net:443/default;transportMode=http;ssl=true;httpPath=/hive2;sasl.qop=auth的连接:javax.net.ssl.SSLPeerUnverifiedException: 主机名'123.123.123.123'与对等方提供的证书主题不匹配(CN=*.azurehdinsight.net)
at org.apache.hive.jdbc.HiveConnection.<init>(HiveConnection.java:256)
at org.apache.hive.jdbc.HiveDriver.connect(HiveDriver.java:107)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at MyFancyButNotWorkingClass.main(MyFancyButNotWorkingClass.java:102)
很明显,将证书添加到密钥库并没有帮助,因为它似乎是为错误的服务器。然而,我(徒劳)的希望是,即使由不同服务器使用,也会接受受信任的证书(这显然会破坏SSL服务器证书的身份验证概念)。
一些证书可以通过将它们添加到本地密钥库中变得可信,例如https://self-signed.badssl.com的示例证书。以下是如何将其添加到密钥库的方式:
%JAVA_HOME%\bin\keytool.exe" -import -file <CERTIFICATE-FILE-NAME> -alias <SOME-NAME> -keystore my-sample-store
配置SSL验证过程的一般方法在Apache HTTP Components - 连接管理 - SSL中有文档记录。根据这份文档(以及在本论坛和其他地方的一些研究),我得出了以下代码:
SSLContext sslContext = SSLContext.getDefault();
HostnameVerifier hostnameVerifier = new NoopHostnameVerifier();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
由于这没有效果,我查看了HiveConnection.java的实现,发现SSLConnectionSocketFactory
是使用不可配置的DefaultHostnameVerifier
初始化的。
我是否遗漏了什么?是否有一种方法可以设置JVM范围内的标准HTTP客户端工厂设置,然后HIVE实现将使用这些设置?
英文:
I wonder how I can customize the SSL certificate validation for the Apache HIVE JDBC driver in Java. This includes enabling the use of self-signed certificates as well as ignoring other validation errors.
This is the code throwing an error:
// using library hive-jdbc-3.1.2-standalone.jar
Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection con = DriverManager.getConnection("jdbc:hive2://somethingsomethinghere.azurehdinsight.net:443/default;transportMode=http;ssl=true;httpPath=/hive2", "user@somedomain.com", "ultra-secure password");
If the code would work, a connection to HIVE would be established and con
would be set accordingly. Instead I get this error:
java.sql.SQLException: Could not open client transport with JDBC Uri: jdbc:hive2://somethingsomethinghere.azurehdinsight.net:443/default;transportMode=http;ssl=true;httpPath=/hive2: Could not establish connection to jdbc:hive2://somethingsomethinghere.azurehdinsight.net:443/default;transportMode=http;ssl=true;httpPath=/hive2;sasl.qop=auth: javax.net.ssl.SSLPeerUnverifiedException: Host name '123.123.123.123' does not match the certificate subject provided by the peer (CN=*.azurehdinsight.net)
at org.apache.hive.jdbc.HiveConnection.<init>(HiveConnection.java:256)
at org.apache.hive.jdbc.HiveDriver.connect(HiveDriver.java:107)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at MyFancyButNotWorkingClass.main(MyFancyButNotWorkingClass.java:102)
It is rather obvious that added the certificate to the key store does not help as it seems to be for the wrong server. However, my (vain) hope was that a trusted certificate would be accepted even if used by a different server (which clearly would break the concept of SSL server certificates for authentication).
Some certificates can be made trustworthy by adding them to a local key store, e.g. the sample certificate of https://self-signed.badssl.com. This is how it is added to a key store:
%JAVA_HOME%\bin\keytool.exe" -import -file <CERTIFICATE-FILE-NAME> -alias <SOME-NAME> -keystore my-sample-store
The general approach to configure the SSL validation process is documented in Apache HTTP Components - Connection Management - SSL. With this documentation (and some research on in this forum and others) I ended up with this code:
SSLContext sslContext = SSLContext.getDefault();
HostnameVerifier hostnameVerifier = new NoopHostnameVerifier();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory).build();
As this had no effect I looked into the implementation of HiveConnection.java and found that the SSLConnectionSocketFactory
is initialized using a non-configurable DefaultHostnameVerifier
.
Am I missing something here? Is there a way to set JVM-wide standard HTTP Client Factory settings that the HIVE implementation will then use?
答案1
得分: 0
如果这能稍作安慰的话,Hive JDBC的版本号<3.x
的jar包即使使用DefaultHostnameVerifier
也能正常工作。
关于同样错误的问题,已经在GitHub上开了一个问题 链接。
英文:
If It's any consolation, Hive JDBC version < 3.x
jars are working even with DefaultHostnameVerifier
.
There is a Github issue opened for the same error Link
专注分享java语言的经验与见解,让所有开发者获益!
评论