在使用Microsoft JDBC驱动程序版本连接到SQL Server数据库时,我收到以下错误:
Com.microsoft.sqlserver.jdbc.SQLServerException:驱动程序无法使用安全套接字层加密与SQL Server建立安全连接。错误:“SQL Server返回不完整的响应。连接已关闭。ClientConnectionId:98d0b6f4-f3ca-4683-939e-7c0a0fca5931”.
我们最近将我们的应用程序从Java 6和Java 7升级到Java 8。所有运行Java的系统都运行SuSE Linux Enterprise Server 11(X86_64),Version=11,PATCHLEVEL=3。
以下是我通过编写的Java程序收集的事实,该程序只需按顺序打开和关闭1,000个数据库连接。
- 大约5%-10%的时间会断开连接,并出现此错误。并非每个连接都会出现该错误。
- 这个问题只在Java 8上出现。我在Java 7上运行了相同的程序,该问题不可重现。这与我们升级前的生产经验是一致的。我们在生产版的Java 7下运行时没有遇到任何问题。
- 并不是所有运行Java 8的Linux服务器都会出现这个问题,它只出现在其中的一些服务器上。这让我很困惑,但当我在不同Linux示例上的相同版本的Linux JVM(1.8.0_60,64位)上运行相同的测试程序时,一个Linux示例上不会出现这个问题,但其他示例上确实会出现这个问题。Linux示例运行相同版本的SuSE,并且它们处于相同的补丁级别。
- 连接到SQL Server 2008和SQL Server 2014服务器/数据库时出现问题。
- 无论我使用的是4.0版的SQL Server JDBC驱动程序还是较新的4.1版驱动程序,都会出现问题。
与网络上的其他人相比,我在这个问题上的独特之处在于,尽管这个问题只发生在Java 8上,但我无法让这个问题发生在运行相同Java 8 JVM的看似相同的Linux服务器上。其他人也在Java的早期版本中看到过这个问题,但这不是我们的经验。
如果您有任何意见、建议或意见,我们将不胜感激。
21条答案
按热度按时间gj3fmq9x1#
您的url应该如下所示,并添加SQL sqljdbc42.jar。这将解决您的问题
aurhwmvo2#
我在一个Linux示例上的Java 8JVM中打开了SSL日志记录,这会重现该问题。使用
-Djavax.net.debug=ssl:handshake:verbose
打开了SSL日志记录。这揭示了一些有用的信息。我们在生产中使用并已证明对我们有效的解决方法是在JVM上设置此参数:
如果您想了解更多细节,请继续阅读。
在可以重现问题的服务器上(同样,只有5%-10%的时间),我观察到以下情况:
请注意,TLSv1.2是数据库服务器选择的,并在本次交换中使用。我观察到,当从有问题的Linux服务连接失败时,TLSv1.2始终是选择的级别。但是,使用TLSv1.2时,连接并不总是失败。他们失败的几率只有5%-10%。
现在,这是一个来自没有问题的服务器的交换。其他一切都是平等的。即,连接到相同的数据库、相同版本的JVM(Java 1.8.0_60)、相同的JDBC驱动程序等。请注意,在这里,数据库服务器选择TLSv1,而不是故障服务器的情况下的TLSv1.2。
因此,当在Linux JVM和SQL Server之间协商TLSv1时,连接总是成功的。当协商TLSv1.2时,我们会收到零星的连接故障。
(注意:Java 7(1.7.0_51)总是与TLSv1协商,这就是为什么我们在使用Java 7 JVM时从来没有出现过这个问题。)
我们仍有一些悬而未决的问题:
1.为什么从两个不同的Linux服务器运行的同一个Java 8 JVM总是协商TLSv1,而当从另一个Linux服务器连接时,它总是协商TLSv1.2。
1.为什么TLSv1.2协商的连接在该服务器上成功的时间最多,但不是全部?
2017年6月10日更新:This posting from Microsoft介绍问题及建议的解决方案。
资源:
http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html
http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html
http://blogs.msdn.com/b/jdbcteam/archive/2008/09/09/the-driver-could-not-establish-a-secure-connection-to-sql-server-by-using-secure-sockets-layer-ssl-encryption.aspx
Java 8 , JCE Unlimited Strength Policy and SSL Handshake over TLS
http://blogs.msdn.com/b/saponsqlserver/archive/2013/05/10/analyzing-jdbc-connection-issues.aspx
Https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#descPhase2
https://blogs.oracle.com/java-platform-group/entry/java_8_will_use_tls
wnavrhmk3#
如果有人来到这里寻找从PhpStorm连接到数据库的解决方案,只需在URL中的端口后添加以下内容:
我从这个评论中得到了解决方案:Java 8上的SQL Server JDBC错误:驱动程序无法使用安全套接字层(SSL)加密建立到SQL Server的安全连接
非常感谢!可以确认它正在PhpStorm 2022.1.1上工作。
rjee0c154#
使用OpenJDK 11,可以将以下属性添加到连接URL以强制使用SSL
;integratedSecurity=false;encrypt=false;trustServerCertificate=true;
zbdgwd5y5#
在升级SQL JDBC驱动程序之前,请先检查兼容性:
来源:https://www.microsoft.com/en-us/download/details.aspx?id=11774
68de4m5k6#
这似乎已在版本4.2的MS SQL JDBC驱动程序中修复。我创建了一个程序,在其中我连接到服务器1000次,每次尝试之间暂停100ms。在4.1版中,我每次都能够重现这个问题,尽管它只是偶尔发生。在4.2版中,我无法重现该问题。
dluptydi7#
当我用MSSQL-jdbc-8.4.1JAR更改sqljdbc-4.2.0JAR时,问题得到了解决
uinbv5nw8#
在我的例子中,我有一个使用3DES_EDE_CBC算法的SQL服务器,这在JDK 1.8上默认是禁用的,所以检查
/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/java.security
并从以下方面消除了该算法:
Jdk.tls.disabled算法=SSLv3、RC4、DES、MD5with RSA、DH密钥大小<1024、\EC密钥大小<224、3DES_EDE_CBC、ANON、NULL
对我很管用。
mzaanser9#
就像@2AGuy写的那样,你可以改变JVM参数。在我的例子中,我无法更改它,而使用了连接字符串“sslProtocol”参数,降低了到TLSV1的连接。
连接字符串:jdbc:sqlserver://:;encrypt=true;trustServerCertificate=true;sslProtocol=TLSv1;database=<DB名称>
1l5u6lss10#
微软最近开放了他们的驱动程序。用户可以在GitHub上看到mssql-jdbc驱动程序活动。我猜最新的预览版是6.1.5。
你也可以在maven上找到所有的预览版本。同时支持JDK7和JDK8。
eni9jsuy11#
我在Windows Server 2012 R2上也遇到过这个问题,使用的是带有Java 7的JDBC驱动程序4.0和4.1。这个Microsoft article将责任归咎于DHE密码套件,并建议在无法升级到JDBC驱动程序4.2的情况下禁用它们或降低它们的优先级
trnvg8h312#
在我的例子中,问题是因为应用程序被设置为使用spring-boot-ext-security-starter-credhub-credential,而该设置存在一些问题。
因此,我从清单文件和POM中删除了CredHub,并以不同的方式获取凭据;然后错误就消失了。
uxh89sit13#
如果连接字符串中的服务器名称与SQL Server SSL证书中的服务器名称不匹配,则会发出以下错误:驱动程序无法使用安全套接字层(SSL)加密建立到SQL Server的安全连接。错误:“在安全套接字层(SSL)初始化期间,无法验证证书中的服务器名称。”
这帮助我解决了这个问题。正在使用ServerName中的本地主机,最终将JDBC连接字符串中的名称更改为CN能够连接的名称。
有关更多信息,请参阅:https://wiki.deepnetsecurity.com/pages/viewpage.action?pageId=1410867
8ftvxx2r14#
感谢@Sunil Kumar和@Joce。我使用了JAR和以下语法:
字符串myDriver=“com.microsoft.jdbc.sqlserver.SQLServerDriver”;
字符串myURL=“jdbc:sqlserver://DB_ipaddress\DB_instance;databaseName=DB_name;user=myusername;password=mypass;encrypt=true;trustServerCertificate=true;”;/==>此处的分号如图所示/
连接con=DriverManager.getConnection(MyURL);
neekobn815#