programing

Java 8에서 SQL Server JDBC 오류: 드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Server에 대한 보안 연결을 설정할 수 없습니다.

subpage 2023. 4. 29. 09:19
반응형

Java 8에서 SQL Server JDBC 오류: 드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Server에 대한 보안 연결을 설정할 수 없습니다.

Microsoft JDBC Driver 버전을 사용하여 SQL Server 데이터베이스에 연결할 때 다음 오류가 발생합니다.

com.vmdk.sqlserver.jdbc.SQL Server 예외:드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Server에 대한 보안 연결을 설정할 수 없습니다.오류: "SQL Server에서 불완전한 응답을 반환했습니다.연결이 닫혔습니다.클라이언트 연결ID: 98d0b6f4-f3ca-4683-939e-7c0a0fca5931".

당사는 최근 애플리케이션을 Java 6 및 Java 7에서 Java 8로 업그레이드했습니다.Java를 실행하는 모든 시스템은 SUSE Linux Enterprise Server 11(x86_64), VERSION = 11, PATCHLEVEL = 3을 실행합니다.

여기 제가 작성한 자바 프로그램으로 수집한 사실들이 있습니다. 자바 프로그램은 1,000개의 데이터베이스 연결을 순차적으로 열고 닫습니다.

  • 연결이 삭제되고 이 오류가 발생하는 경우는 약 5%-10%입니다.모든 연결에서 오류가 발생하는 것은 아닙니다.
  • 문제는 Java 8에서만 발생합니다.자바 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에서 이 문제를 본 적이 있지만, 우리의 경험은 그렇지 않습니다.

귀하의 의견, 제안 또는 의견에 감사드립니다.

당신의 URL은 아래와 같아야 하며 sqljdbc42.jar를 추가해야 합니다.이렇게 하면 문제가 해결됩니다.

url = "jdbc:sqlserver://" +serverName + ":1433;DatabaseName=" + dbName + ";encrypt=true;trustServerCertificate=true;

문제를 재현하는 Linux 인스턴스에서 Java 8 JVM에서 SSL 로깅을 설정했습니다. 로은다사용설정다를 하여 설정됩니다.-Djavax.net.debug=ssl:handshake:verbose이것은 몇 가지 유용한 정보를 드러냈습니다.

운영 환경에서 사용하고 있으며 효과가 입증된 해결 방법은 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를 협상합니다.
  2. 또한 TLSv1.2가 해당 서버에서 모든 시간이 아닌 대부분의 시간 동안 협상된 연결이 성공적인 이유는 무엇입니까?

2017년 6월 10일 업데이트: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 무제한 강도 정책 및 TLS를 통한 SSL 핸드셰이크

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

PphpStorm에서 데이터베이스에 연결하기 위한 솔루션을 찾는 사람이 여기에 도착하는 경우 URL의 포트 뒤에 다음을 추가합니다.

;encrypt=true;trustServerCertificate=true;

여기에 이미지 설명 입력

이 의견에서 해결책을 얻었습니다. Java 8에서 SQL Server JDBC 오류: 드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Server에 대한 보안 연결을 설정할 수 없습니다.

정말 감사합니다!PphpStorm 2022.1.1에서 작동하는지 확인할 수 있습니다.

openjdk 11을 사용하면 SSL 사용을 강제하기 위해 다음 속성을 연결 URL에 추가할 수 있습니다.

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

SQL JDBC 드라이버를 업그레이드하기 전에 먼저 호환성을 확인하십시오.

  • Sqljdbc.jar에는 JRE 5가 필요하며 JDBC 3.0 API를 지원합니다.
  • Sqljdbc4.jar에는 JRE 6이 필요하며 JDBC 4.0 API를 지원합니다.
  • Sqljdbc41.jar에는 7의 JRE가 필요하며 JDBC 4.1 API를 지원합니다.
  • Sqljdbc42.jar에는 8의 JRE가 필요하며 JDBC 4.2 API를 지원합니다.

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

더하다;encrypt=true;trustServerCertificate=trueurl.connection.url 파일에 됩니다.»

jdbc:sqlserver://localhost\SQLEXPRESS:1433;databaseName=testdb;encrypt=true;trustServerCertificate=true

그리고 mssql-jdbc 버전이 maven인 pom 파일의 Compatible 컴파일러 버전 java를 확인합니다.이것처럼.

<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>

그리고.

<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>11.2.1.jre8</version>
</dependency>

컴파일러 1.8 및 jre8

이 문제는 MS SQL JDBC 드라이버 버전 4.2에서 해결된 것으로 보입니다.저는 서버에 1,000번 연결하여 각 시도마다 100ms씩 일시 정지하는 프로그램을 만들었습니다.버전 4.1에서는 산발적으로만 문제가 발생했지만 매번 문제를 재현할 수 있었습니다.버전 4.2에서는 문제를 재현할 수 없었습니다.

sqljdbc-4.2.0 jar를 mssql-jdbc-8.4.1 jar로 변경했을 때 문제가 해결되었습니다.

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

나의 경우 3DES_EDE_CBC 알고리즘을 사용하는 SQL 서버가 있었는데, jdk 1.8에서는 기본적으로 비활성화되어 있으므로,

/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/콘텐츠/홈/jre/lib/security/java.security

알고리즘을 제거할 알고리즘 제거:

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, RSA가 있는 MD5, DH keySize < 1024, \ EC keySize < 224, 3DES_EDE_CBC, anon, NULL

나를 위해 일했습니다.

@2Aguy가 작성한 것처럼 JVM 파라미터를 변경할 수 있습니다.제 경우에는 변경할 수 없었고 연결 문자열 "sslProtocol" 매개 변수를 사용하여 TLSV1에 대한 연결을 낮췄습니다.

연결 문자열: jdbc:sqlserver://<HOST>:<PORT>;암호화=true;trustServerCertificate=true;sslProtocol=TLSv1; 데이터베이스=<DB NAME >

  • application.properties:
    spring.datasource.url=jdbc:sqlserver://YourServerName:1433;database=<YourDatabaseName>;encrypt=true;trustServerCertificate=true;
    spring.datasource.username=root
    spring.datasource.password=1234
    spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
    spring.jpa.show-sql=true
    spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
    spring.jpa.properties.hibernate.globally_quoted_identifiers=true
    spring.jpa.hibernate.ddl-auto = create-drop

@Sunil Kumar와 @Joce 덕분입니다.저는 jar와 아래 구문을 사용했습니다.

myDriver = "com.dll.jdbc.sqlserver를 문자열로 지정합니다.SQL Server 드라이버";

문자열 myURL = "jdbc:sqlserver://DB_ipaddress\DB_instance; databaseName=DB_name;user=myusername; 암호=mypass; 암호=true; trustServerCertificate=true;"/==> 여기서 세미콜론은 두 배로 표시됩니다/

Connection con = DriverManager.getConnection(myURL);

Microsoft 최근에 드라이버를 공개했습니다.GitHub에서 mssql-jdbc 드라이버 작업을 볼 수 있습니다.가장 최근의 프리뷰 버전은 6.1.5인 것 같습니다.

또한 메이븐에서도 모든 미리보기 버전을 찾을 수 있습니다.JDK7 및 JDK8을 모두 지원합니다.

또한 Java 7에서 JDBC 드라이버 4.0 및 4.1을 사용하여 Windows Server 2012 R2에서 이 문제를 해결했습니다.Microsoft 문서는 DHE 암호 스위트를 비난하며, JDBC 드라이버 4.2로 업그레이드할 수 없는 경우 이 암호 스위트를 사용하지 않도록 설정하거나 우선 순위를 낮출 것을 권장합니다.

저의 경우, 문제는 앱이 spring-boot-ext-security-starter-credhub-credential을 사용하도록 설정되어 있고 해당 설정에 몇 가지 문제가 있었기 때문입니다.

그래서 매니페스트 파일과 폼에서 credhub를 제거하고 다른 방법으로 credhub을 가져왔는데, 오류가 사라졌습니다.

연결 문자열의 서버 이름이 SQL Server SSL 인증서의 서버 이름과 일치하지 않으면 다음 오류가 발생합니다.드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Server에 대한 보안 연결을 설정할 수 없습니다.오류: "java.security.cert"입니다.인증서.예외:SSL(Secure Sockets Layer)을 초기화하는 동안 인증서에서 서버 이름의 유효성을 검사하지 못했습니다."

이것은 제가 문제를 해결하는 데 도움이 되었습니다.서버 이름에서 localhost를 사용하고 있었습니다. 마지막으로 jdbc 연결 문자열을 CN이 연결할 수 있는 동일한 이름으로 변경했습니다.

자세한 내용은 https://wiki.deepnetsecurity.com/pages/viewpage.action?pageId=1410867 를 참조하십시오.

저는 제 지역 환경에서 문제를 해결했습니다. 주로 아래의 두 단계를 포함하고 있습니다.

  1. 프로젝트가 메이븐에 의해 구축된 경우 아래와 같이 JDBC 드라이버 종속성을 전환합니다.
<dependency>
  <groupId>net.sourceforge.jtds</groupId>
  <artifactId>jtds</artifactId>
  <version>1.3.1</version>
</dependency>

2. 드라이버 클래스 이름을 추가로 바꿉니다.

ru.yandex.clickhouse.ClickHouseDriver

3.JDBC URL을 다음과 같이 수정합니다.

jdbc:jtds:sqlserver://xxxx:1433;databaseName=xxx

SQL 데이터베이스를 연결하는 동안 이 문제에 직면했습니다.잘못된 JAR 파일로 인해 이 문제가 발생했습니다.

내가 사용한 연결 URL

 "jdbc:sqlserver://localhost:8080;databaseName=db_name;encrypt=true;trustServerCertificate=true";

"sqljdbc4-2.0.jar" JAR 파일을 사용하기 전에는 사용할 수 없었습니다.

일단 내가 이 JAR 파일을 변경한 후에는 잘 작동했습니다.

mssql-jdbc-8.4.1.jre8.jar

최근 RedHat 7을 실행하는 고객의 서버에서 yum 업데이트를 한 후 이 문제가 발생하였습니다. 위 스레드가 제 문제를 해결하는 데 도움이 되지 않아 이 답변을 올립니다.

문제:- RedHat의 Yum 업데이트는 OpenJDK를 자동으로 재설치합니다. 내 애플리케이션은 Oracle JDK를 사용합니다.기본 JDK 확인 중:

java version 기본 버전 전환:

update-alternative --config java

'자바'를 제공하는 프로그램은 2가지가 있습니다.

선택 명령

  • 1 java-1.8.0-openjdk.x86_64(/usr/lib/jvm/dll-1.8.0-openjdk-1.8.0.302.b08-0.el7_9.x86_64/jre/bin/dll)
  • 2 /usr/slot/jdk1.8.0_181-48064/jre/bin/slot

현재 선택 [+]를 유지하거나 선택 번호를 입력합니다.

원하는 버전 옆에 번호를 입력하고 Enter 키를 누릅니다.

아래 연결 문자열로 데이터베이스에 연결하는 동안에도 동일한 문제가 발생했습니다.

DriverManager.getConnection("jdbc:sqlserver://" + host + ":" + port + ";databaseName=" + dbName + ";user=" + userName + ";password=" + password);

아래와 같이 연결 문자열을 업데이트한 후 작동했습니다.

Connection con = DriverManager.getConnection("jdbc:sqlserver://" + host + ":" + port + ";databaseName=" + dbName + ";encrypt=true;trustServerCertificate=true;user=" + userName + ";password=" + password);

에 여에추가습니다했기다니▁added를 했습니다.encrypt=true;trustServerCertificate=true데이터베이스 이름 뒤에 있습니다.

나를 위해 나는 추가합니다.Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

DriverManager.registerDriver(new com.microsoft.sqlserver.jdbc.SQLServerDriver());

Connection con = DriverManager.getConnection(connectionUrl);

따라서 연결의 최종 코드는 다음과 같습니다.

    DriverManager.registerDriver(new com.microsoft.sqlserver.jdbc.SQLServerDriver());
    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    Connection con = DriverManager.getConnection(connectionUrl);

점화 8.1+ 오류로 여기에 왔는데 로컬 호스트에서 MSSQL Express를 사용하는 경우 "연결 URL"에 jdbc:sqlserver://localhost\SQLPRESS; encrypt=true; trustServerCertificate=true; URL 설정을 입력합니다.

유효한 연결

setTrustServerCertificate(true); 

나를 위해 일했습니다.

언급URL : https://stackoverflow.com/questions/32766114/sql-server-jdbc-error-on-java-8-the-driver-could-not-establish-a-secure-connect

반응형