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

标签 java sql-server ssl jdbc

我正在使用此代码在 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 实例,我会得到一个异常(exception):
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 驱动程序使用我添加的任何证书,它必须正常进行并忽略它们?
我有另一台使用相同 JDK 版本和相同 JDBC 驱动程序的 Ubuntu 机器,以及包含我的应用程序的相同 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。连接尝试作为无效的数据库地址返回。

最佳答案

在 Mark Rotteveel 和 AlwaysLearning 的帮助下,这个问题得以解决。
它与我加载到 OpenJDK1.8 信任库中的 SSL 证书无关。
问题是三方面的。
首先,在我的 Netbeans 11 项目中,在“Dependencies”文件夹中,我有一个名为
MSSQL-4.0.jar
这显然是由该项目的先前开发人员手动放置的。
我删除了这个文件 - 我不知道正在使用哪个驱动程序,因为我有一个如上所述的 Maven 工件,还有 MSSQL JDBC 驱动程序。
其次,AlwaysLearning 然后好心地指出,我与 MSSQL 的连接异常是指 SQLLite(不是 MSSQL),并且 SQLLite 驱动程序报告了无效数据库地址的异常,而不是 MSSQL 驱动程序。
核心问题是,由于某种原因,当我尝试使用上述源代码连接到 MSSQL 时,MSSQL JDBC 驱动程序正在尝试与 MSSQL 建立 SQLLite 连接。
这就是为什么我不断得到

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

当然,SQLLite 连接协议(protocol)永远不会在 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/security/java.security 我更改了行
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 工件(因为它不再在我的项目中使用,并且是一个遗留库)。一旦 SQLLite 库在下一次编译中被 Maven 删除,并且我编辑了 java.security 文件,如上所述,生成的 .JAR 能够从我的 Ubuntu 机器连接到 MSSQL 服务器,之后我降低了/中的安全要求etc/java-8-openjdk/security/java.security 并使用 OpenJDK1.8 安装在 Ubuntu 机器上重新启动我的应用程序。
这是因为 MSSQL JDBC 驱动程序现在使用“正版”MSSQL 协议(protocol)来尝试从我的 Ubuntu 机器连接到 MSSQL 服务器,而不是尝试使用 SQLLite 协议(protocol)连接到 MSSQL 服务器,-并且- JDBC 驱动程序是在更改 java.security 后,允许与 MSSQL 服务器谈论“足够老”的 TLS 版本。
希望这对其他人有帮助。
斯特凡

关于java - sqljdbc4.jar - 无法连接到 MSSQL 服务器实例 - SSL 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68600351/

相关文章:

sql - 如何用一个 Sql 查询可视化两个外键

sql - LEFT JOIN 匹配。如果没有匹配,需要在最近的日期匹配

java - SpannableString 可以序列化吗?

java - Minecraft 1.9 模组 block 渲染错误

java - Eclipse 每次打开都会崩溃并关闭

java - 什么是 Java 字符串池以及 "s"与新字符串 ("s"有何不同?

java - 检查数据库中是否有表

ssl - 如何使用 Bro 捕获 https 流量的元数据

java - 如果我们传递 javax ssl 参数,Google Cloud Storage Client API 在证书验证中失败

ssl - keystore 不能在 wildfly 中使用 CA 证书