You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle数据库JDBC SSL连接异常求助:连接被主机软件中止

Oracle JDBC TCPS连接报错:java.sql.SQLRecoverableException 排查方案

按照Oracle官方文档配置JDBC SSL(TCPS)连接时,出现连接被主机软件中止的IO错误,异常信息如下:

java.sql.SQLRecoverableException: IO Error: An established connection was aborted by the software in your host machine, connect lapse 16 ms., Authentication lapse 0 ms.
at oracle.jdbc.driver.T4CConnection.handleLogonIOException(T4CConnection.java:915)

当前使用的连接代码:

public static java.sql.Connection getConnection(String user, String password) throws MalformedURLException, InstantiationException, IllegalAccessException, ClassNotFoundException
{
    String trustStoreWalletPath="C://input//cwallet.sso" , keyStoreWalletPath="C://input//cwallet.sso";
    Security.addProvider(new oracle.security.pki.OraclePKIProvider());
    Security.insertProviderAt(new oracle.security.pki.OraclePKIProvider(),3);
    Properties property = new Properties();
    property.setProperty("oracle.net.authentication_services","(TCPS)");
    property.setProperty("javax.net.ssl.trustStore", trustStoreWalletPath);//
    property.setProperty("javax.net.ssl.trustStoreType", "SSO");
    property.setProperty("javax.net.ssl.keyStore", keyStoreWalletPath);
    property.setProperty("javax.net.ssl.keyStoreType", "SSO");
    String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=xx.dm.xyz.com)(PORT=2484))(CONNECT_DATA=(SERVICE_NAME=xx.dm.xyz.com)))";
    property.setProperty("user", user);
    property.setProperty("password", password);

    try {
        Connection c = DriverManager.getConnection(url, property);
        return c;

    } catch (SQLException throwables) {
        throwables.printStackTrace();
        return null;
    }
}

以下是针对性的排查和修复方案:


1. 修正Wallet路径与权限

  • Windows路径建议使用单斜杠/或双反斜杠\\,把C://input//cwallet.sso改为C:/input/cwallet.sso或C:\\input\\cwallet.sso,避免路径解析异常。
  • 确保运行Java程序的用户对cwallet.sso文件有读取权限,如果文件放在系统受限目录(如C:\Windows),需要调整权限或移动文件位置。

2. 修复OraclePKIProvider加载逻辑

当前代码重复添加了OraclePKIProvider,保留一个即可,推荐使用insertProviderAt确保优先级,避免Provider冲突:

// 只保留这一行即可
Security.insertProviderAt(new oracle.security.pki.OraclePKIProvider(), 3);

同时确认项目依赖包含oraclepki.jar、osdt_core.jar、osdt_cert.jar这三个Oracle PKI核心包,缺少会导致SSO类型密钥库无法解析。

3. 匹配Oracle端TCPS配置

  • 检查数据库端2484端口是否正常监听:执行lsnrctl status命令,确认TCPS协议的监听状态,同时排查防火墙是否允许该端口的双向流量。
  • 验证URL中的SERVICE_NAME是否正确:必须与Oracle端lsnrctl status输出的服务名完全一致。
  • 可尝试在URL中添加服务器证书DN校验,确保与数据库证书匹配:
    String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=xx.dm.xyz.com)(PORT=2484))(CONNECT_DATA=(SERVICE_NAME=xx.dm.xyz.com))(SECURITY=(SSL_SERVER_CERT_DN=\"CN=你的服务器证书DN\")))";
    
    证书DN可通过openssl s_client -connect xx.dm.xyz.com:2484命令查看证书详情获取。

4. 调整SSL版本与加密套件

若驱动与数据库端SSL版本不兼容,可在Properties中强制指定SSL版本:

property.setProperty("oracle.net.ssl_version", "TLSv1.2");

或指定兼容的加密套件(需与数据库端配置一致):

property.setProperty("oracle.net.ssl_cipher_suites", "(SSL_RSA_WITH_AES_256_CBC_SHA)");

5. 启用SSL调试日志定位问题

添加JVM参数开启SSL调试日志,查看握手过程细节:

-Djavax.net.debug=ssl,handshake

日志会显示证书验证、密钥交换等步骤的错误信息,帮助定位是证书信任、协议不兼容还是其他底层问题。

6. 使用Oracle专属Wallet属性替代JDK标准属性

对于Oracle SSO Wallet,推荐使用Oracle专属属性加载,避免JDK标准SSL属性的兼容性问题:

// 替换原有的trustStore/keyStore配置
property.setProperty("oracle.net.wallet_location", "(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=C:/input)))");

该属性会自动加载指定目录下的cwallet.sso文件,无需单独指定密钥库类型和路径。


修复后的示例代码

public static java.sql.Connection getConnection(String user, String password) throws ClassNotFoundException
{
    String walletDir = "C:/input";
    Security.insertProviderAt(new oracle.security.pki.OraclePKIProvider(), 3);
    
    Properties property = new Properties();
    property.setProperty("oracle.net.authentication_services", "(TCPS)");
    property.setProperty("oracle.net.wallet_location", "(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=" + walletDir + ")))");
    property.setProperty("oracle.net.ssl_version", "TLSv1.2");
    
    String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=xx.dm.xyz.com)(PORT=2484))(CONNECT_DATA=(SERVICE_NAME=xx.dm.xyz.com)))";
    property.setProperty("user", user);
    property.setProperty("password", password);

    try {
        Class.forName("oracle.jdbc.OracleDriver");
        Connection c = DriverManager.getConnection(url, property);
        return c;
    } catch (SQLException throwables) {
        throwables.printStackTrace();
        return null;
    }
}

内容的提问来源于stack exchange,提问作者lifeline2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 06:36:22