MSSQL2008 和 JDK17 的问题

今天上午忙于调试 Windsurf 工具,结果一直无法正常使用,心情十分烦躁。更糟糕的是,数据库又出了问题。

我们的数据库是较旧的 MSSQL2008,今天发现数据表一直无法读取,这让我非常郁闷。经过排查,问题出在 SSL 版本上。由于 JDK17 是较新的版本,它不再支持 TLS1.0 和 TLS1.1,而我们的 MSSQL2008 服务器恰好使用的是 TLS1.0,这就导致了连接失败。

以下是部分异常日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2025-05-07T15:52:34.061+08:00 DEBUG 22000 --- [io-8080-exec-12] c.g.m.log.dao.SysLogErrorDao.insert      : ==> Parameters: 1920023939057827841(Long), /metahub-admin/mm/dataSourcesAdd/tableList(String), POST(String), Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36(String), 0:0:0:0:0:0:0:1(String), java.lang.RuntimeException: com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12]". ClientConnectionId:7b55ddc5-755c-4a8f-b1a3-3c4b6f5b06cc
at com.geendata.modules.metahub.mm.service.impl.MmDataSourcesAddServiceImpl.tableList(MmDataSourcesAddServiceImpl.java:568)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:723)
at com.geendata.modules.metahub.mm.service.impl.MmDataSourcesAddServiceImpl$$SpringCGLIB$$0.tableList(<generated>)
at com.geendata.modules.metahub.mm.controller.MmDataSourcesAddController.tableList(MmDataSourcesAddController.java:182)
at jdk.internal.reflect.GeneratedMethodAccessor172.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at com.geendata.common.aspect.LogOperationAspect.around(LogOperationAspect.java:53)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:642)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:632)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:173)
at org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor$1.proceed(AopAllianceAnnotationsAuthorizingMethodInterceptor.java:82)

为了解决这个问题,我尝试了以下几种方法:

• 添加参数,允许使用 TLS1.0 或 TLS1.1

尝试在启动参数中添加-Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2",但效果不佳。

• 使用低版本的 JDBC 驱动

下载并安装了较旧版本的 Microsoft JDBC 驱动,但仍然无法解决问题。

• 给数据库打补丁,升级 TLS

考虑给数据库服务器打补丁以升级 TLS 版本,但由于不想给客户带来过多麻烦,暂时搁置了这个方案。

• 修改 JDK17 的安全策略,允许使用 TLS1.0 或 TLS1.1

最终,我修改了 JDK17 的安全策略文件。具体操作如下:

• 找到D:\Java\jdk-17\conf\security目录下的java.security文件。

• 找到以下内容:

1
2
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL

• 删除TLSv1, TLSv1.1,,修改后的内容如下:

1
2
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL

• 保存文件后重新启动程序,问题终于解决了。

通过以上步骤,我成功解决了 JDK17 与 MSSQL2008 之间因 TLS 版本不兼容导致的连接问题。虽然这种方法可以暂时解决问题,但仍然建议尽快升级数据库服务器以支持更高版本的 TLS,以提高安全性。