Oracle中ORA-29273与ORA-29024证书验证失败问题求助
问题场景
执行以下PL/SQL代码访问HTTPS内网站点时,触发ORA-29024: Certificate validation failure错误:
DECLARE l_url VARCHAR2(50) := 'https://www.domainname.net'; l_http_request UTL_HTTP.req; l_http_response UTL_HTTP.resp; BEGIN -- 发送HTTP请求并获取响应 utl_http.set_wallet('file:WALLETPATH', 'pass'); l_http_request := UTL_HTTP.begin_request(l_url); l_http_response := UTL_HTTP.get_response(l_http_request); UTL_HTTP.end_response(l_http_response); END;
错误详情:
ERROR at line 1:
ORA-29273: HTTP request failed
ORA-29024: Certificate validation failure
ORA-06512: at "SYS.UTL_HTTP", line 380
ORA-06512: at "SYS.UTL_HTTP", line 1148
ORA-06512: at line 9
已完成前置操作:
- 为
www.domainname.net配置ACL权限(对应文件/sys/acls/domainname-net-permissions.xml) - 创建Oracle Wallet,通过
orapki wallet display -wallet可正常查看证书内容 - 服务器本地浏览器可正常访问目标域名
排查与解决步骤
1. 确认Wallet路径与权限
- 确保
utl_http.set_wallet中的路径为绝对路径,格式为file:/完整路径(例如file:/opt/oracle/wallets/mywallet),避免使用相对路径。 - 检查Oracle进程所属用户(通常为
oracle)对Wallet目录及文件拥有读权限:chown -R oracle:oinstall /path/to/wallet chmod -R 700 /path/to/wallet
2. 验证证书链完整性
浏览器会自动补全缺失的中间CA证书,但Oracle UTL_HTTP不会。使用以下命令查看完整证书链:
orapki wallet display -wallet /path/to/wallet -complete
- 确认Wallet中包含目标站点的根CA证书、中间CA证书(如果存在)以及站点证书,缺少任何一环都会导致验证失败。
- 检查证书是否过期,确认证书的
Validity区间包含当前时间。
3. 检查TLS版本兼容性
目标站点可能仅支持特定TLS版本(如TLS 1.2/1.3),而UTL_HTTP默认版本不匹配。可显式指定TLS版本:
DECLARE l_url VARCHAR2(50) := 'https://www.domainname.net'; l_http_request UTL_HTTP.req; l_http_response UTL_HTTP.resp; BEGIN utl_http.set_wallet('file:/完整路径', 'pass'); UTL_HTTP.SET_SECURITY_PROTOCOL(UTL_HTTP.SSL_VERSION_TLS_1_2); -- 指定TLS 1.2 l_http_request := UTL_HTTP.begin_request(l_url); l_http_response := UTL_HTTP.get_response(l_http_request); UTL_HTTP.end_response(l_http_response); END;
注意:Oracle 11gR2需要安装补丁才能支持TLS 1.2,12c及以上版本默认支持。
4. 验证主机名匹配
确认证书的**CN(通用名称)或SAN(主题备用名称)**与访问的www.domainname.net完全一致。如果证书仅包含domainname.net,则需要添加www.domainname.net到证书的SAN字段,或调整访问URL为https://domainname.net。
5. 临时关闭证书验证(仅测试用)
若以上步骤无法快速定位问题,可临时关闭证书验证确认是否为证书链问题(生产环境禁止使用):
DECLARE l_url VARCHAR2(50) := 'https://www.domainname.net'; l_http_request UTL_HTTP.req; l_http_response UTL_HTTP.resp; BEGIN utl_http.set_wallet('file:/完整路径', 'pass'); UTL_HTTP.SET_VERIFY_CERTIFICATE(FALSE); -- 关闭验证 l_http_request := UTL_HTTP.begin_request(l_url); l_http_response := UTL_HTTP.get_response(l_http_request); UTL_HTTP.end_response(l_http_response); END;
如果代码执行成功,说明证书链存在缺失,需要补全对应的CA证书到Wallet中。
内容的提问来源于stack exchange,提问作者Krishnakumar B

