Tomcat通过TCPS连接Oracle失败:网络适配器无法建立连接
我有一个运行在Tomcat上的Servlet文档管理系统(DMS),依赖Oracle 19c数据库。为了安全,要加密Tomcat和Oracle的连接。
已经用orapki在Oracle 19c上创建了带自签名证书的钱包,配置了listener.ora、sqlnet.ora和tnsnames.ora,同时修改了Servlet的config.xml连接字符串为TNS格式。TCP协议能正常连接,但用TCPS时出现“网络适配器无法建立连接”错误。
SQLplus可以正常建立TCPS连接,求排查问题。
环境信息
Server1: Linux Oracle Server 7.8 Oracle 19c Hostname: oracleserver.localdomain Server2: Windows Server 2022 Datacenter Apache Tomcat 9.0.37 OpenJDK 15.0.1+9-18 Hostname elo
Oracle服务器配置文件
listener.ora
LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oracleserver.localdomain)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) (ADDRESS = (PROTOCOL = TCPS)(HOST = oracleserver.localdomain)(PORT = 2484)) ) ) WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /u01/app/oracle/product/19.0.0/dbhome_1/wallets/server_wallet) ) ) SSL_CLIENT_AUTHENTICATION = FALSE
SQLnet.ora
SQLNET.AUTHENTICATION_SERVICES = (BEQ,TCPS) NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT) WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /u01/app/oracle/product/19.0.0/dbhome_1/wallets/server_wallet) ) ) SSL_CLIENT_AUTHENTICATION = FALSE
tnsnames.ora
LISTENER = (ADDRESS = (PROTOCOL = TCP)(HOST = oracleserver.localdomain)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCPS)(HOST = oracleserver.localdomain)(PORT = 2484)) ELO = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oracleserver.localdomain)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = elo) ) ) ELOPDB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCPS)(HOST = oracleserver.localdomain)(PORT = 2484)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = elopdb) ) )
Tomcat配置
Java参数
-Djava.net.preferIPv4Stack=true -Doracle.net.ssl_cipher_suites=SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_C4_128_MD5, SSL_DH_anon_WITH_DES_CBC_SHA
JDBC连接字符串
jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL=TCPS)(HOST=oracleserver)(PORT=2484)))(CONNECT_DATA=(SERVICE_NAME=ELOPDB)(SERVER=DEDICATED)))
错误信息
19:45:25.690 WARN eloix-init-2 init-2 (DBConnection.java:486) - Could not establish connection using jdbcurl=jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL=TCPS)(HOST=oracleserver)(PORT=2484)))(CONNECT_DATA=(SERVICE_NAME=ELOPDB)(SERVER=DEDICATED))), I/O-Fehler: The Network Adapter could not establish the connection 19:45:25.695 WARN eloix-init-2 init-2 (IXServlet$InitThread.java:539) - Initialization error, retry after 10s java.sql.SQLException: java.sql.SQLException: Cannot get connection from Driver Manager. DB[1] Command="" at de.elo.ix.db.DBConnection.throwException(DBConnection.java:175) at de.elo.ix.db.DBConnection.internalConnect(DBConnection.java:583) at de.elo.ix.db.DBConnection.connect(DBConnection.java:357) at de.elo.ix.data.DBFactory.createAndConnect(DBFactory.java:14) at de.elo.ix.exec.ServerObject.init(ServerObject.java:1138) at de.elo.ix.exec.ServerObjectHolderImpl.init(ServerObjectHolderImpl.java:47) at de.elo.ix.IXServlet$InitThread.run(IXServlet.java:521) Caused by: java.sql.SQLException: Cannot get connection from Driver Manager. at de.elo.ix.db.DBConnection.internalConnect(DBConnection.java:551) ... 5 common frames omitted
已尝试的解决方案
- 在Windows服务器安装Oracle客户端工具,使用别名作为连接字符串,仍报相同错误
- SQL Plus和
openssl s_client -connect oracleserver:2484均可正常建立TCPS连接 - 添加以下Java参数,问题依旧:
-Doracle.net.wallet_location=D:\App\Oracle\product\19.3.0\dbhome_1\network\admin -Doracle.net.tns_admin=D:\App\Oracle\product\19.3.0\dbhome_1\network\admin
排查方向与解决建议
1. JDBC驱动版本兼容性问题
Oracle JDBC驱动对不同JDK版本、Oracle版本的兼容性要求严格。你使用的是OpenJDK 15,需确认当前使用的Oracle JDBC驱动版本是否支持JDK 15以及TCPS连接。建议升级到对应Oracle 19c的最新JDBC驱动(ojdbc8或ojdbc11,JDK 15推荐ojdbc11)。
2. 主机名解析问题
连接字符串中使用的HOST=oracleserver,需确认Windows服务器(elo)是否能正确解析该主机名到Oracle服务器的IP地址。可以尝试在连接字符串中直接替换为Oracle服务器的IP地址,测试是否能连接。
3. Java信任库未导入Oracle证书
虽然使用了匿名DH加密套件(SSL_DH_anon_*),但部分JDBC驱动版本仍要求服务器证书被Java信任库信任。可以将Oracle钱包中的自签名证书导出,导入到Windows服务器的OpenJDK信任库(cacerts文件,路径一般为JDK_HOME/lib/security/cacerts):
- 导出证书:在Oracle服务器执行
orapki wallet export -wallet /u01/app/oracle/product/19.0.0/dbhome_1/wallets/server_wallet -dn "CN=oracleserver.localdomain" -cert server.crt - 将
server.crt复制到Windows服务器 - 导入到cacerts:
keytool -import -alias oracle-tcps -file server.crt -keystore "path/to/cacerts" -storepass changeit
4. Java参数配置问题
- 检查
oracle.net.ssl_cipher_suites中的套件是否与Oracle服务器支持的套件匹配。可以在Oracle服务器查看listener日志或执行tnsping ELOPDB确认支持的套件,确保Java参数中的套件在服务器支持列表内。 oracle.net.wallet_location参数指向的路径是否正确?该路径应指向包含ewallet.p12和cwallet.sso文件的钱包目录,而非network/admin目录。你当前设置的路径需确认是否存在钱包文件,若没有,需修改为实际钱包路径。
5. Tomcat网络权限限制
检查Windows服务器的防火墙是否允许Tomcat进程访问Oracle服务器的2484端口。虽然openssl s_client能连接,但Tomcat进程可能被防火墙规则限制。可以临时关闭Windows防火墙测试,或添加允许Tomcat访问2484端口的规则。
6. 连接字符串格式问题
尝试简化连接字符串,去掉ADDRESS_LIST(单个地址时不需要),改为:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=oracleserver.localdomain)(PORT=2484))(CONNECT_DATA=(SERVICE_NAME=ELOPDB)(SERVER=DEDICATED)))
同时确认SERVICE_NAME是否与Oracle服务器的elopdb服务名完全匹配(区分大小写)。
内容的提问来源于stack exchange,提问作者Chillkroetle

