Java 8上的SQL Server JDBC错误:驱动程序无法使用安全套接字层(SSL)加密与SQL Server建立安全连接 [英] SQL Server JDBC Error on Java 8: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption

查看:1616
本文介绍了Java 8上的SQL Server JDBC错误:驱动程序无法使用安全套接字层(SSL)加密与SQL Server建立安全连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Microsoft JDBC驱动程序版本连接到SQL Server数据库时出现以下错误:

I am getting the following error when connecting to a SQL Server database using version the Microsoft JDBC Driver:


com.microsoft.sqlserver .jdbc.SQLServerException:驱动程序无法使用安全套接字层(SSL)加密与SQL Server建立安全连接。错误:SQL Server返回不完整的响应。连接已关闭.ClientConnectionId:98d0b6f4-f3ca-4683-939e-7c0a0fca5931。

com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "SQL Server returned an incomplete response. The connection has been closed. ClientConnectionId:98d0b6f4-f3ca-4683-939e-7c0a0fca5931".



<我们最近从Java 6& Java 7到Java 8.所有运行Java的系统都运行SUSE Linux Enterprise Server 11(x86_64),VERSION = 11,PATCHLEVEL = 3.

We recently upgraded our applications from Java 6 & Java 7 to Java 8. All systems running Java are running SUSE Linux Enterprise Server 11 (x86_64), VERSION = 11, PATCHLEVEL = 3.

以下是我的事实使用我编写的Java程序收集,只需按顺序打开和关闭1,000个数据库连接。

Here are the facts I have collected with a Java program that I wrote which simply sequentially opens and closes 1,000 database connections.


  • 连接被丢弃,此错误大约为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版驱动程序,都会出现问题。

  • Connections are dropped with this error about 5%-10% of the time. The error DOES NOT occur on every connection.
  • The problem ONLY occurs with Java 8. I ran the same program on Java 7 and the problem is not reproducible. This is consistent with our experience in production prior to upgrading. We've had zero problems running under Java 7 in production.
  • The problem DOES NOT occur on all of our Linux servers running Java 8, it only occurs on some of them. This is perplexing to me, but when I run the same test program on the same version of the Linux JVM (1.8.0_60, 64 bit) on different Linux instances, the problem does not occur on one of the Linux instances, but the problem does occur on others. The Linux instances are running the same version of SUSE and they are at the same patch level.
  • The problem occurs when connecting to BOTH SQL Server 2008 and SQL Server 2014 servers/databases.
  • The problem occurs regardless if I am using the 4.0 version of the SQL Server JDBC driver or the newer 4.1 version of the driver.

与网络上的其他人相比,使我的观察结果独一无二的是,尽管问题仅发生在Java 8上,但我无法在看似相同的Linux服务器上发生问题。正在运行相同的Java 8 JVM。其他人也在早期版本的Java上看到了这个问题,但这不是我们的经验。

The thing that makes my observations unique on this compared to others on the web is that although the problem happens ONLY on Java 8, I cannot get the problem to occur on one of the seemingly identical Linux servers that is running the same Java 8 JVM. Other folks have seen this problem on earlier versions of Java as well, but that has not been our experience.

您可能会对任何输入,建议或观察结果表示赞赏。

Any input, suggestions, or observations you may have are appreciated.

推荐答案

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

I turned on SSL logging in the Java 8 JVM on a Linux instance which reproduces the problem. SSL logging is turned on using -Djavax.net.debug=ssl:handshake:verbose. This revealed some useful information.

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

The workaround that we are using in production and has proven to work for us is to set this parameter on the JVM:

 -Djdk.tls.client.protocols=TLSv1

如果您想了解更多详情,请继续阅读。

If you want more details, please read on.

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

On a server where the problem can be reproduced (again, only 5-10% of the time), I observed the following:

*** 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%的时间内失败。

Notice that TLSv1.2 is selected by the database server and used in this exchange. I've observed that, when connections fail from the problematic linux service, TLSv1.2 is ALWAYS the level which was selected. However, connections do not ALWAYS fail when TLSv1.2 is used. They only fail 5-10% of the time.

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

Now here is an exchange from a server that does NOT have the problem. Everything else is equal. I.e., connecting to the same database, same version of the JVM (Java 1.8.0_60), same JDBC driver, etc. Notice that, here, TLSv1 is selected by the database server instead of TLSv1.2 as in the faulty server's case.

*** 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时,我们会出现零星的连接故障。

So, when TLSv1 is negotiated between the Linux JVM and the SQL Server, connections are ALWAYS successful. When TLSv1.2 is negotiated, we get sporadic connection failures.

(注意:Java 7(1.7.0_51)总是协商TLSv1,这就是我们使用Java 7 JVM时从未发生过问题的原因。)

(Note: Java 7 (1.7.0_51) always negotiates TLSv1, which is why the problem never occurred for us with a Java 7 JVM.)

我们仍有的问题是:


  1. 为什么同样的Java 8 JVM从2个不同的Linux服务器将始终协商TLSv1,但是当从另一个Linux服务器连接时,它总是协商TLSv1.2。

  2. 为什么TLSv1.2协商连接在该服务器上的成功率最高,但不是全部?

更新6/10/2017:
来自Microsoft的帖子描述了问题及其建议的解决方案。

Update 6/10/2017: This posting from Microsoft describes the problem and their proposed solution.

资源:

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/操作系统/更多补丁问题 - 报告与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无限强度政策和TLS上的SSL握手

http://blogs.msdn .com / b / saponsqlserver / archive / 2013/05/10 / analyze-jdbc-connection-issues.aspx

https://docs.oracle.com/javase/8/docs/技术说明/指南/ security / jsse / JSSERefGuide.html #descPhase2

https://blogs.oracle.com/java-platform-group/entry/java_8_will_use_tls

这篇关于Java 8上的SQL Server JDBC错误:驱动程序无法使用安全套接字层(SSL)加密与SQL Server建立安全连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆