【发布时间】:2025-12-30 00:00:16
【问题描述】:
我正在使用此代码在 Ubuntu 机器上使用 sqljdbc4.jar 从 OpenJDK1.8 连接到 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 类上的直接通过 ip 连接无关,我通过我的 B 类 LAN 连接到本地 MSSQL 实例。
为什么 MSSQL JDBC 驱动程序突然导致涉及证书的明显异常,并拒绝连接?
我不希望 JDBC 驱动程序使用我添加的任何证书,它必须正常进行并忽略它们?
我有另一台 Ubuntu 机器使用相同的 JDK 版本和相同的 JDBC 驱动程序,以及包含我的应用程序的相同 JAR,它在 OpenJDK1.8 证书存储中没有任何用户添加的证书,它可以连接到相同的 MSSQL 服务器使用 JDBC 驱动程序和相同的连接字符串,没问题。
为什么要为我从 Java 应用程序连接到的 Internet 上的不相关域添加 SSL 证书,现在显然会导致该应用程序中的 MSSQL Java JDBC 驱动程序尝试使用来自 OpenJDK1.8 证书存储的随机 SSL 证书连接到本地by-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 连接问题没有影响 e。 G。连接尝试作为无效的数据库地址返回。
【问题讨论】:
-
您确定您没有意外删除现有证书吗?您最近是否在两台机器上运行过更新?
-
您好,谢谢您的回复。我实际上只是为域添加了 .der 证书文件。一台机器是最近安装的带有 OpenJDK1.8 的全新 Ubuntu 20.21,另一台是大约 3 个月前更新的 Ubuntu 20.21,直到那时为止,使用 OpenJDK1.8.... 旧安装的机器仍在工作,新的昨天加载的证书是 JDBC 实例无法连接的。
-
尝试记录 SSL 调试(使用
-Djavax.net.debug=all启动您的应用程序),另请参阅 Debugging SSL/TLS Connections。此外,最近的 Java 版本默认禁用了一些较旧的 TLS 版本。确保两者的jre/lib/security/java.security配置文件相同。 -
谢谢 Mark 尝试过,我只是将数万行记录到控制台,看起来很正常(至少有几百行。)这就是我从应用程序建立两个 SSL 连接的事情到两台服务器,并且在两个实例中都能 100% 工作 - 较旧的 Ubuntu 实例应用程序和较新的 Ubuntu 实例应用程序 - 实际上只是 MSSQL JDBC 连接在较新的 Ubuntu 实例上失败,其中一个看起来是 JDBC 驱动程序试图使用 MSSQL 服务器端不支持的证书与 MSSQL 服务器建立 SSL 连接。
-
我建议仅创建一个基本应用程序来重现该问题,如果您可以重现它,则启用该日志记录。它应该查明 SSL 握手失败的地方(假设是失败的地方)。
标签: java sql-server ssl jdbc