sqljdbc4.jar语言 - 无法连接到MSSQL服务器实例- SSL错误?



我使用这段代码从OpenJDK1.8使用sqljdbc4.jar连接到MSSQL 2012实例:

public static DataSource getMsSqlPoolSource(String server, String database, String user, String password) throws ClassNotFoundException {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String connectionString = "jdbc:sqlserver://" + server + ";databaseName=" + database + ";sendStringParametersAsUnicode=false;";
System.out.println("Connection String for MSSQL is:: " + connectionString);
org.apache.commons.dbcp2.ConnectionFactory factory = new DriverManagerConnectionFactory(connectionString, user, password);
PoolableConnectionFactory poolFactory = new PoolableConnectionFactory(factory, null);
ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolFactory);
poolFactory.setPool(connectionPool);
PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
return dataSource;
}

这工作了三年,直到今天。

如果我现在尝试从同一个Ubuntu盒子连接到过去三年相同的MSSQL 2012实例,我得到一个异常:

2021-07-31 10:01:07.125 ERROR vsCallLogSyncOnVerinet - SQL ERROR:: 1jyg0yezlh46 - invalid database address: jdbc:sqlserver://172.16.1.244;databaseName=my_DB;sendStringParametersAsUnicode=false;
Security providers: [SUN version 1.8, SunRsaSign version 1.8, SunEC version 1.8, SunJSSE version 1.8, SunJCE version 1.8, SunJGSS version 1.8, SunSASL version 1.8, XMLDSig version 1.8, SunPCSC version 1.8]
SSLContext provider info: Sun JSSE provider(PKCS12, SunX509/PKIX key/trust factories, SSLv3/TLSv1/TLSv1.1/TLSv1.2/TLSv1.3)
SSLContext provider services:
[SunJSSE: KeyFactory.RSA -> sun.security.rsa.RSAKeyFactory$Legacy
aliases: [1.2.840.113549.1.1, OID.1.2.840.113549.1.1]
, SunJSSE: KeyPairGenerator.RSA -> sun.security.rsa.RSAKeyPairGenerator$Legacy
aliases: [1.2.840.113549.1.1, OID.1.2.840.113549.1.1]
, SunJSSE: Signature.MD2withRSA -> sun.security.rsa.RSASignature$MD2withRSA
aliases: [1.2.840.113549.1.1.2, OID.1.2.840.113549.1.1.2]
, SunJSSE: Signature.MD5withRSA -> sun.security.rsa.RSASignature$MD5withRSA
aliases: [1.2.840.113549.1.1.4, OID.1.2.840.113549.1.1.4]
, SunJSSE: Signature.SHA1withRSA -> sun.security.rsa.RSASignature$SHA1withRSA
aliases: [1.2.840.113549.1.1.5, OID.1.2.840.113549.1.1.5, 1.3.14.3.2.29, OID.1.3.14.3.2.29]
, SunJSSE: Signature.MD5andSHA1withRSA -> sun.security.ssl.RSASignature
, SunJSSE: KeyManagerFactory.SunX509 -> sun.security.ssl.KeyManagerFactoryImpl$SunX509
, SunJSSE: KeyManagerFactory.NewSunX509 -> sun.security.ssl.KeyManagerFactoryImpl$X509
aliases: [PKIX]
, SunJSSE: TrustManagerFactory.SunX509 -> sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory
, SunJSSE: TrustManagerFactory.PKIX -> sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory
aliases: [SunPKIX, X509, X.509]
, SunJSSE: SSLContext.TLSv1 -> sun.security.ssl.SSLContextImpl$TLS10Context
aliases: [SSLv3]
, SunJSSE: SSLContext.TLSv1.1 -> sun.security.ssl.SSLContextImpl$TLS11Context
, SunJSSE: SSLContext.TLSv1.2 -> sun.security.ssl.SSLContextImpl$TLS12Context
, SunJSSE: SSLContext.TLSv1.3 -> sun.security.ssl.SSLContextImpl$TLS13Context
, SunJSSE: SSLContext.TLS -> sun.security.ssl.SSLContextImpl$TLSContext
aliases: [SSL]
, SunJSSE: SSLContext.Default -> sun.security.ssl.SSLContextImpl$DefaultSSLContext
, SunJSSE: KeyStore.PKCS12 -> sun.security.pkcs12.PKCS12KeyStore
]
java.ext.dirs: /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext:/usr/java/packages/lib/ext

我最近在OpenJDK1.8证书存储中添加了一些证书,用于与我通过B类LAN连接到本地MSSQL实例的本地B类上的直接ip连接无关的两个域。

为什么MSSQL JDBC驱动程序突然导致涉及证书的明显异常,并拒绝连接?

我不希望JDBC驱动程序使用我添加的任何证书,它必须正常进行并忽略它们?

我有另一台使用相同JDK版本和相同JDBC驱动程序的Ubuntu机器,以及包含我的应用程序的相同JAR,它在OpenJDK1.8证书存储中没有用户添加的任何类型的证书,并且它可以使用具有相同连接字符串的JDBC驱动程序连接到相同的MSSQL服务器,没有问题。

为什么要为我从Java应用程序连接到的互联网上的不相关域添加SSL证书,现在显然会导致该应用程序中的MSSQL Java JDBC驱动程序尝试使用来自OpenJDK1.8证书存储的随机SSL证书连接到本地ip B类网络上的本地MSSQSL服务器?

证书是这样添加的:

/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/keytool -trustcacerts -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -alias lets-encrypt-x3-cross-signed -file lets-encrypt-x3-cross-signed.der
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/keytool -trustcacerts -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -alias lets-encrypt-x3-cross-signed2 -file isrg-root-x1-cross-signed.der
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/keytool -trustcacerts -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -alias lets-encrypt-x3-cross-signed3 -file lets-encrypt-r3.der

编辑:设法确定上面添加的SSH证书不是问题-如果我从信任存储中删除它们,JDBC连接的问题仍然存在,与上面完全相同。因此,加载的SSH证书对JDBC连接问题没有影响,例如,连接尝试返回为无效的数据库地址。

在Mark Rotteveel和AlwaysLearning的帮助下,这个问题得到了解决。

这与我加载到OpenJDK1.8信任存储中的SSL证书无关。

问题有三个方面。

首先,在我的Netbeans 11项目中,在"Dependencies"文件夹中,有一个jar名为

MSSQL-4.0.jar

显然是由项目的前一个开发人员手动放置的。

我删除了这个文件-我不知道正在使用哪个驱动程序,因为我有一个maven工件,如上面详细介绍的,也是用于MSSQL JDBC驱动程序。

其次,AlwaysLearning然后友好地指出,我的连接异常到MSSQL是指SQLLite(不是MSSQL),一个无效的数据库地址的异常是由SQLLite驱动程序报告的,而不是MSSQL驱动程序。

核心问题是,由于某种原因,当我尝试使用上述源代码连接到MSSQL时,MSSQL JDBC驱动程序正在尝试使用sqlite连接到MSSQL。

这就是为什么我总是收到

java.sql.SQLException: invalid database address:jdbc:sqlserver://172.17.12.14;databaseName=DB;sendStringParametersAsUnicode=false;

当然,sqlite连接协议永远不会在MSSQL服务器上工作…

第三,连接到MSSQL的异常随后改变为MSSQL服务器对连接使用了太旧的TLS加密,而我的客户端在JDBC端拒绝了这一点——见上文。Mark Rotteveel随后协助编辑文件

/etc/java-8-openjdk/security/java.security

在我的Ubuntu 20.11 LTS OpenJKD1.8安装上降低TLS的安全性,以便我的OpenJDK1.8实例将允许TLS加密级别(我试图连接到的相当旧的MSSQL实例)。

/etc/java-8-openjdk/安全/java。我改了行

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, 
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, 
include jdk.disabled.namedCurves

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, 
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, 
include jdk.disabled.namedCurves

所以总而言之,从我的NetBeans项目的"依赖"中删除虚假的MSSQL-4.0.jar后;文件夹中,我还注释掉了SQLLite的Maven构件(因为它不再在我的项目中使用,并且是一个遗留库)。在下一次编译时,Maven删除了sqlite库,然后我编辑了java。在我降低了/etc/java-8-openjdk/security/java中的安全要求之后,生成的. jar能够从我的Ubuntu机器连接到MSSQL服务器。在Ubuntu机器上使用OpenJDK1.8安装重新启动我的应用程序。

这是因为MSSQL JDBC驱动程序现在使用的是"正版";MSSQL协议,试图从我的Ubuntu机器连接到MSSQL服务器,而不是试图使用sqlite协议连接到MSSQL服务器,并且- JDBC驱动程序被允许"足够老"地说话;java.security.

修改后到MSSQL服务器的TLS版本希望这对别人有帮助。

Stefan

最新更新