Wallet是Oracle原生证书容器(含cwallet.sso),JDBC直接识别;JKS是Java标准密钥库,需JVM参数加载,二者不可混用,否则触发ORA-28860等SSL错误。
Oracle JDBC 连接 SSL 时 Wallet 和 JKS 的本质区别
wallet 是 oracle 原生的证书容器格式(ewallet.p12 + cwallet.sso),jdbc 驱动(ojdbc8.jar 及以上)能直接识别;jks 是 java 标准密钥库,需通过 jvm 参数或 javax.net.ssl.* 系统属性加载。二者不能混用——用 wallet 就别配 javax.net.ssl.truststore,否则驱动会忽略 wallet 并报 ora-28860: ssl/tls error。
常见错误现象:java.sql.SQLRecoverableException: IO Error: The Network Adapter could not establish the connection,实际是 SSL 握手失败,但错误不提示证书问题。
- Wallet 路径必须是绝对路径,相对路径在 Spring Boot 或容器中极易失效
- JDK 17+ 默认禁用 TLS 1.0/1.1,Oracle 12cR2+ 要求显式启用
TLSv1.2,Wallet 中的证书也得支持该协议 - Wallet 必须包含完整的信任链(CA 证书 + 中间证书),只放根 CA 会导致握手失败
用 ojdbc8 加载 Wallet 的最小配置
Oracle 官方推荐方式:不依赖 JVM SSL 参数,靠 JDBC URL 和 Wallet 目录控制。关键点是 oracle.net.wallet_location 必须指向含 cwallet.sso 的目录,且文件权限不能开放(Linux/macOS 下需 chmod 600 cwallet.sso,否则驱动拒绝加载)。
示例连接 URL:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=mydb.example.com)(PORT=2484))(CONNECT_DATA=(SERVICE_NAME=orcl)))
对应 Java 属性设置:
立即学习“Java免费学习笔记(深入)”;
-
oracle.net.wallet_location=/path/to/wallet/dir(不是文件,是目录) -
javax.net.ssl.trustStore、javax.net.ssl.keyStore等 JVM 参数必须清空或未设置 - Driver 类必须是
oracle.jdbc.OracleDriver(ojdbc8.jar自动注册,无需Class.forName)
JKS 方式下绕不开的三个 JVM 参数陷阱
如果必须用 JKS(例如和现有 Spring Boot SSL 配置统一),就得走标准 Java SSL 流程,但 Oracle JDBC 会复用 JVM 的 SSL 上下文——这就导致参数稍错就静默失败。
-
javax.net.ssl.trustStore必须指向 JKS 文件(如/etc/ssl/oracle-trust.jks),不能是 PKCS#12 -
javax.net.ssl.trustStorePassword若为空字符串,JVM 会报Keystore was tampered with, or password was incorrect,必须设为changeit或真实密码 -
oracle.net.ssl_versionJDBC 属性必须显式设为TLSv1.2(尤其 JDK 17+),否则可能降级到不支持的协议
错误场景:Spring Boot 的 server.ssl.* 配置和数据库连接共用同一 JKS,结果 HTTPS 正常、JDBC 报 SSLHandshakeException: Received fatal alert: handshake_failure——因为服务端只接受客户端证书认证,而 JDBC 没传 client cert。
验证 Wallet 或 JKS 是否生效的快速方法
别等应用启动失败再排查。最直接的是用 sqlplus 或 ojdbc_test 工具本地验证 Wallet 路径和内容:
- 运行
mkstore -wrl /path/to/wallet -list,确认输出含Trusted Certificates条目 - 用
keytool -list -v -keystore your-trust.jks检查 JKS 是否含正确 alias 和 valid until 日期 - 在 JDBC 连接代码前加
System.setProperty("oracle.jdbc.Trace", "true"),日志里搜Wallet location或TrustManagerFactory,看驱动是否真读到了你指定的路径
最容易被忽略的是 Wallet 的加密状态:cwallet.sso 是加密的,ewallet.p12 是明文(仅用于导出)。驱动只认 cwallet.sso,改名或替换文件后不重启 JVM,旧缓存仍生效。










