相同Oracle连接串在SQL Developer可用,独立JDBC程序却报连接重置异常
两类环境连接表现不一致的核心原因
报错堆栈中出现的
javax.net.ssl.SSLException: Connection reset,本质是SSL/TLS握手阶段被对端主动中断的典型表现,并非网络层面完全不通。
- 第一,驱动与SSL栈的能力存在代差。当前使用的ojdbc6 11.2.0.3是2011年发布的早期JDBC驱动,原生TCPS连接最高仅支持TLSv1协议,对TLS1.2及以上版本没有做适配;而SQL Developer内置的是经过多轮迭代的TLS实现,默认对高低版本TLS协议、加密套件的兼容性是打通的,能自动和服务端协商到匹配的加密套件。现在绝大多数Oracle数据库的TCPS监听都已经在服务端禁用了TLSv1及更早的协议、弱加密套件,老版本驱动发起的握手请求会被数据库监听直接判定为非法请求,主动reset连接。
- 第二,配置加载逻辑存在差异。SQL Developer会自动加载内置的信任证书库,自动补全TCPS握手必须的安全参数(比如证书DN校验、SSL版本协商参数);但独立Java程序使用的ojdbc驱动默认完全不预置任何数据库根证书,也不会自动补SECURITY段的必要参数,就算连接串写了TCPS,也会因为握手参数不全被服务端断连。
- 第三,存在JDK默认安全策略的冲突。多数使用ojdbc6的场景都是跑在JDK8及以上版本上,高版本JDK默认会禁用老的加密算法、低版本TLS协议,和老驱动自带的SSL实现逻辑完全不匹配,两边协商不拢就会直接中断连接。
可落地的调整方案
- 优先替换适配的驱动版本。淘汰ojdbc6 11.2.0.3这个存在大量TCPS兼容缺陷的版本,根据当前使用的JDK版本匹配对应驱动:如果是JDK8及以上,直接替换为ojdbc8 12.2.0.1以上的稳定版本,该系列驱动原生完整支持TLS1.2/1.3的TCPS连接,和主流数据库的监听配置完全兼容。如果业务限制必须在JDK6/7环境运行,至少要升级到ojdbc6 11.2.0.4的最终补丁版本,手动开启驱动对TLS1.2的支持开关。
- 手动配置SSL信任链路。将数据库TCPS对应的根证书导入Java运行环境的信任库,或者在启动Java程序时通过JVM参数显式指定自定义信任库路径和密码:
-Djavax.net.ssl.trustStore=/自定义信任库的绝对路径 -Djavax.net.ssl.trustStorePassword=信任库对应的密码 - 修正连接串补全必要安全参数。不要直接把SQL Developer里的连接串照搬给JDBC程序,需要在连接串的DESCRIPTION段下追加SECURITY配置段,补全驱动触发正确SSL握手必须的参数:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=hostName)(PORT=1546))(CONNECT_DATA=(SERVICE_NAME=serviceName))(SECURITY=(SSL_VERSION=TLSv1.2)(SSL_SERVER_CERT_DN=数据库服务端证书的DN值))) - 调整JVM的TLS协商策略。启动程序时强制指定客户端支持的TLS版本,匹配数据库监听的要求,同时放开被JDK默认禁用的加密套件列表:
-Djdk.tls.client.protocols=TLSv1.2
如果数据库端使用的加密套件在JDK的默认禁用列表里,需要同步在java.security文件里移除对应的禁用规则,避免握手阶段被本地JVM拦截。 - 排查中间网络干扰。如果按以上步骤调整后还是报连接重置,可以通过通用TLS测试工具测试1546端口的TLS握手连通性,确认本地到数据库监听的路径上没有防火墙、代理设备因为不识别老版本SSL握手包直接丢弃连接。
内容的提问来源于stack exchange,提问作者Divya Rakshu
相关产品推荐
相关产品推荐

