Java 8上的SQL Server JDBC错误:驱动程序无法使用安全套接字层(SSL)加密建立到SQL Server的安全连接

pgx2nnw8  于 2022-09-18  发布在  Java
关注(0)|答案(21)|浏览(468)

在使用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的早期版本中看到过这个问题,但这不是我们的经验。

如果您有任何意见、建议或意见,我们将不胜感激。

dluptydi

dluptydi16#

当我用MSSQL-jdbc-8.4.1JAR更改sqljdbc-4.2.0JAR时,问题得到了解决

<dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>mssql-jdbc</artifactId>
      <version>8.4.1.jre8</version>
</dependency>
68de4m5k

68de4m5k17#

这似乎已在版本4.2的MS SQL JDBC驱动程序中修复。我创建了一个程序,在其中我连接到服务器1000次,每次尝试之间暂停100ms。在4.1版中,我每次都能够重现这个问题,尽管它只是偶尔发生。在4.2版中,我无法重现该问题。

zbdgwd5y

zbdgwd5y18#

在升级SQL JDBC驱动程序之前,请先检查兼容性:

  • Sqljdbc.jar要求JRE为5,支持JDBC 3.0 API
  • Sqljdbc4.jar要求JRE为6,支持JDBC 4.0 API
  • Sqljdbc41.jar要求JRE为7,支持JDBC 4.1 API
  • Sqljdbc42.jar要求JRE为8,支持JDBC 4.2 API

来源:https://www.microsoft.com/en-us/download/details.aspx?id=11774

rjee0c15

rjee0c1519#

使用OpenJDK 11,可以将以下属性添加到连接URL以强制使用SSL

;integratedSecurity=false;encrypt=false;trustServerCertificate=true;

wnavrhmk

wnavrhmk20#

如果有人来到这里寻找从PhpStorm连接到数据库的解决方案,只需在URL中的端口后添加以下内容:

;encrypt=true;trustServerCertificate=true;

我从这个评论中得到了解决方案:Java 8上的SQL Server JDBC错误:驱动程序无法使用安全套接字层(SSL)加密建立到SQL Server的安全连接

非常感谢!可以确认它正在PhpStorm 2022.1.1上工作。

aurhwmvo

aurhwmvo21#

我在一个Linux示例上的Java 8JVM中打开了SSL日志记录,这会重现该问题。使用-Djavax.net.debug=ssl:handshake:verbose打开了SSL日志记录。这揭示了一些有用的信息。

我们在生产中使用并已证明对我们有效的解决方法是在JVM上设置此参数:

-Djdk.tls.client.protocols=TLSv1

如果您想了解更多细节,请继续阅读。

在可以重现问题的服务器上(同样,只有5%-10%的时间),我观察到以下情况:


***ClientHello, TLSv1.2

--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 195
main, READ: TLSv1.2 Handshake, length = 1130

***ServerHello, TLSv1.2

--- 8<-- SNIP -----
%% Initialized:  [Session-79, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256]

**TLS_DHE_RSA_WITH_AES_128_GCM_SHA256

--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----

***Diffie-Hellman ServerKeyExchange

--- 8<-- SNIP -----

***ServerHelloDone
***ClientKeyExchange, DH

--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 133
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Change Cipher Spec, length = 1

***Finished

verify_data:  { 108, 116, 29, 115, 13, 26, 154, 198, 17, 125, 114, 166 }

***

main, WRITE: TLSv1.2 Handshake, length = 40
main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT:  warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)
main, waiting for close_notify or alert: state 5
main, received EOFException: ignored
main, called closeInternal(false)
main, close invoked again; state = 5
main, handling exception: java.io.IOException: SQL Server returned an incomplete response. The connection has been closed. ClientConnectionId:12a722b3-d61d-4ce4-8319-af049a0a4415

请注意,TLSv1.2是数据库服务器选择的,并在本次交换中使用。我观察到,当从有问题的Linux服务连接失败时,TLSv1.2始终是选择的级别。但是,使用TLSv1.2时,连接并不总是失败。他们失败的几率只有5%-10%。

现在,这是一个来自没有问题的服务器的交换。其他一切都是平等的。即,连接到相同的数据库、相同版本的JVM(Java 1.8.0_60)、相同的JDBC驱动程序等。请注意,在这里,数据库服务器选择TLSv1,而不是故障服务器的情况下的TLSv1.2。


***ClientHello, TLSv1.2

--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 207
main, READ: TLSv1 Handshake, length = 604

***ServerHello, TLSv1

--- 8<-- SNIP -----
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA
--- 8<-- SNIP -----
%% Initialized:  [Session-79, TLS_RSA_WITH_AES_128_CBC_SHA]

**TLS_RSA_WITH_AES_128_CBC_SHA

--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----

***
***ServerHelloDone
***ClientKeyExchange, RSA PreMasterSecret, TLSv1

--- 8<-- SNIP -----
main, WRITE: TLSv1 Handshake, length = 134
main, WRITE: TLSv1 Change Cipher Spec, length = 1

***Finished

verify_data:  { 26, 155, 166, 89, 229, 193, 126, 39, 103, 206, 126, 21 }

***

main, WRITE: TLSv1 Handshake, length = 48
main, READ: TLSv1 Change Cipher Spec, length = 1
main, READ: TLSv1 Handshake, length = 48

***Finished

因此,当在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

相关问题