ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

【JDK高版本连接SQLServer TLS1.0握手失败问题分析与解决方案】

【JDK高版本连接SQLServer TLS1.0握手失败问题分析与解决方案】 最近在重构一套第三方数据对接的应用本以为按部就班改造完成就可以顺利上线结果直接卡在数据库连接环节。第三方数据库是 SQL Server对外只开放 TLS1.0 协议且目前暂不做升级支持。 当前项目升级到高版本 JDK 之后启动直接抛出 SSL 握手异常无法建立数据库连接。dependency groupIdcom.microsoft.sqlserver/groupId artifactIdmssql-jdbc/artifactId version12.6.2.jre11/version /dependency这个报错相信很多开发的同学都遇到过。 JDK 从 8u291 之后、JDK17、JDK21 版本出于安全考虑已经默认把 TLS1.0、TLS1.1 加入禁用算法列表不再允许客户端使用这两个不安全协议发起连接。 但现实业务很无奈第三方系统不归我们维护对方短期内没有计划升级 TLS 版本我们的项目又必须升级 JDK两边矛盾撞在一起就出现了这个棘手的兼容问题。今天把这次踩坑完整记录下来包含问题根因、几套可行方案还有最重要的安全风险提醒避免大家直接照搬方案留下线上隐患。问题根源第三方 SQL Server 服务端仅支持 TLS1.0没有开启 TLS1.2/1.3第三方现状对接的SQL Server数据库仅支持 TLS 1.0无更高版本TLS协议适配配置第三方暂无升级数据库与安全协议的计划应用现状项目JDK完成版本升级后默认彻底禁用、不再兼容TLS 1.0弱协议安全配置java.security中jdk.tls.disabledAlgorithms默认禁用 TLSv1、TLSv1.1客户端握手直接拒绝旧协议这并不是 JDBC 驱动版本问题是 JVM 层面的安全策略限制哪怕连接字符串指定协议也会被 JDK 拦截。不是代码bug而是JDK官方安全策略的硬性迭代规则。4 套可选解决方案按推荐优先级排序✅方案 1推动第三方升级服务端 TLS最优强烈建议优先争取让合作方把 SQL Server 服务器开启 TLS1.2彻底废弃 TLS1.0。 TLS1.0 存在已知安全漏洞存在中间人攻击、数据泄露风险已经被各大安全标准废弃。缺点主动权不在我方很多第三方排期漫长短期无法落地。⚠️方案 2JVM 启动参数临时放开 TLS1.0临时应急方案不修改 JDK 原始配置文件通过启动参数开启低版本协议应用级别生效。通过外部安全配置覆盖当前 Java 进程的安全属性。数据库 JDBC 驱动指定sslProtocolTLSv1。url: jdbc:sqlserver://地址:1433;databaseNameRunAAA;encryptfalse;trustServerCertificatetrue;sslProtocolTLSv1创建文件/opt//config/legacy-sqlserver.security内容jdk.tls.disabledAlgorithmsSSLv3, TLSv1.1, DTLSv1.0, RC4, DES, MD5withRSA, DH keySize 1024, EC keySize 224, 3DES_EDE_CBC, anon, NULL与 Java 17默认值相比仅移除了TLSv1其他弱算法继续保持禁用。启动java \ -Djava.security.properties/opt/config/legacy-sqlserver.security \ -jar /opt/etl-api.jar如果通过 systemd 启动可以在服务文件中配置[Service] ExecStart/usr/bin/java -Djava.security.properties/opt/config/legacy-sqlserver.security -jar /opt/etl-api.jar修改后执行systemctl daemon-reload systemctl restart etl-api如果使用 DockerCOPY legacy-sqlserver.security /app/config/legacy-sqlserver.security ENTRYPOINT [ java, -Djava.security.properties/app/config/legacy-sqlserver.security, -jar, /app/etl-api.jar ]特点不修改 JDK 安装文件仅影响当前 的Java进程删除启动参数即可回退JDK升级不会覆盖配置最适合当前场景注意虽然没有修改 JDK 文件但该进程运行时的 Java 安全策略确实被调整了。⚠️方案 3修改java.security安全配置文件临时应急方案修改 JDK 配置文件conf/security/java.security从jdk.tls.disabledAlgorithms配置中删除TLSv1, TLSv1.1这两项重启 Java 进程生效。​​​​​​​# legacy-sqlserver.security # 相比当前 JDK 配置仅移除 TLSv1其余弱算法仍保持禁用 jdk.tls.disabledAlgorithmsSSLv3, TLSv1.1, DTLSv1.0, RC4, DES, MD5withRSA, DH keySize 1024, EC keySize 224, 3DES_EDE_CBC, anon, NULL数据库 JDBC 驱动指定sslProtocolTLSv1。url: jdbc:sqlserver://地址:1433;databaseNameRunAAA;encryptfalse;trustServerCertificatetrue;sslProtocolTLSv1最后重启服务。特点配置方式简单所有使用该 JDK 的 Java应用都会受到影响JDK升级或重新安装可能覆盖修改回退需要恢复备份或重新加入TLSv1扩大了 TLS 1.0的影响范围巨大弊端该方案等于允许 JDK 使用不安全的 TLS1.0只作为临时过渡手段一定要设置好后续升级时间点不能当成永久解法。修改 JDK 底层全局配置容器部署场景镜像会被改动版本升级会丢失配置整个 JVM 全部应用都会放开 TLS1.0扩大安全攻击面生产环境改动 JDK 配置需要完整安全评审不建议直接使用。❌方案 4回退 JDK 到老版本尽量避免退回到 JDK8u291 之前版本绕开禁用 TLS1.0 的安全策略。缺点丧失 JDK 新版本安全补丁违背我们做 JDK 升级的初衷技术债务越堆越高。因为第三方短期内无法完成 TLS 升级我们不能回退 JDK 版本。 我们选择JVM 启动参数作为临时过渡方案同时做两件事给第三方输出了安全风险说明文档推动对方排期升级 TLS1.2最终达到彻底解决对接服务做独立隔离这个只用来对接第三方的应用单独部署不影响业务核心服务缩小风险范围。容易踩的坑提醒不要只改 JDBC 连接 url 参数sslProtocolTLSv1高版本 JDK 会直接拦截只改连接串不会解决问题TLS1.0 是不安全协议线上使用一定要做好风险评估不要当成永久兼容方案Docker 容器环境修改java.security文件要注意镜像重建会丢失改动不要直接改镜像内 JDK 文件完成第三方 TLS 升级之后务必第一时间删掉 JVM 放开 TLS1.0 的参数恢复默认安全策略。这次JDK升级对接翻车本质是企业技术迭代与老旧第三方服务滞后的典型矛盾。对开发者而言这不是复杂技术难题但却是高频、极易阻塞迭代的线上问题JDK高版本淘汰TLS1.0是安全合规的必然趋势而老旧SQL Server固守弱协议是历史技术债务。做后端开发经常会遇到这种两难场景我们想要推进技术栈升级但外部老旧第三方系统拖后腿。 技术上总有临时兼容的解法但兼容不等于默许一定要记住临时方案的 “到期时间”不要让临时补丁永久留在生产环境埋下安全隐患。希望能给大家带来帮助。
返回列表