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

前端 未结 8 2158
鱼传尺愫
鱼传尺愫 2020-11-27 16:39

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

com.microsoft.sqlserver.jdbc.SQLSer

相关标签:
8条回答
  • 2020-11-27 16:57

    In my case, the issue was because the app was set to use spring-boot-ext-security-starter-credhub-credential and there were some issues with that setup.

    So I removed credhub from the manifest file and pom and fetched credentials in a different way; then the error was gone.

    0 讨论(0)
  • 2020-11-27 17:02

    This appears to have been fixed in version 4.2 of the MS SQL JDBC driver. I created a program where I connected to the server 1000 times, pausing 100ms between each attempt. With version 4.1 I was able to reproduce the problem every time, although it happened only sporadically. With version 4.2 I was unable to reproduce the problem.

    0 讨论(0)
  • 2020-11-27 17:02

    I've also hit this issue on Windows Server 2012 R2, using JDBC driver 4.0 & 4.1 with Java 7. This Microsoft article pins the blame on DHE ciphersuites, and recommends disabling them or reducing their priority if you cannot upgrade to JDBC driver 4.2

    0 讨论(0)
  • 2020-11-27 17:10

    Before you upgrade SQL JDBC Driver, check the compatibility first:

    • Sqljdbc.jar requires a JRE of 5 and supports the JDBC 3.0 API
    • Sqljdbc4.jar requires a JRE of 6 and supports the JDBC 4.0 API
    • Sqljdbc41.jar requires a JRE of 7 and supports the JDBC 4.1 API
    • Sqljdbc42.jar requires a JRE of 8 and supports the JDBC 4.2 API

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

    0 讨论(0)
  • 2020-11-27 17:14

    Your url should be like below and add sql sqljdbc42.jar. This will resolve your issue

    url = "jdbc:sqlserver://" +serverName + ":1433;DatabaseName=" + dbName + ";encrypt=true;trustServerCertificate=true;
    
    0 讨论(0)
  • 2020-11-27 17:17

    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.

    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.

    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
    

    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.

    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
    

    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.

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

    The open questions we still have are:

    1. WHY is that the same Java 8 JVM run from 2 different Linux servers will always negotiate TLSv1, but when connecting from another Linux server it always negotiates TLSv1.2.
    2. And also why are TLSv1.2 negotiated connections successful most, but not all, of the time on that server?

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

    Resources:

    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

    0 讨论(0)
提交回复
热议问题