ORA-28860: 使用UTL_HTTP时发生致命的SSL错误?

4
我们正在使用 Oracle 11g(11.2.0.3.0),在执行 UTL_HTTP 调用时遇到以下错误:
EXCEPTION: ORA-28860: Fatal SSL error
EXCEPTION: ORA-06512: at "SYS.UTL_HTTP", line 1128
ORA-06512: at line 23

EXCEPTION: ORA-28860: Fatal SSL error

这是我们正在使用的代码:
DECLARE
  url_chr             VARCHAR2(500);
  user_id_chr         VARCHAR2(100);
  password_chr        VARCHAR2(20);
  wallet_path_chr     VARCHAR2(500);
  wallet_pass_chr     VARCHAR2(20);

  l_http_request      UTL_HTTP.REQ;
  l_http_response     UTL_HTTP.RESP; 
  l_text              VARCHAR2(32767);
BEGIN
  url_chr           := '*****';
  user_id_chr       := '*****';
  password_chr      := '*****';
  wallet_pass_chr   := '*****';
  wallet_path_chr   := 'file:/etc/ORACLE/WALLETS/astens/rtca/cer/';

  UTL_HTTP.SET_DETAILED_EXCP_SUPPORT(TRUE);    

  UTL_HTTP.SET_WALLET(wallet_path_chr, wallet_pass_chr);

  l_http_request  := UTL_HTTP.BEGIN_REQUEST(url_chr);
  UTL_HTTP.SET_AUTHENTICATION(r => l_http_request, username => user_id_chr, PASSWORD => password_chr);
  l_http_response := UTL_HTTP.GET_RESPONSE(l_http_request);

  DBMS_OUTPUT.PUT_LINE ('STATUS_CODE : ' || l_http_response.STATUS_CODE);

  BEGIN
    LOOP
      UTL_HTTP.READ_TEXT(l_http_response, l_text, 32766);
      DBMS_OUTPUT.PUT_LINE (l_text);
    END LOOP;
  EXCEPTION
    WHEN UTL_HTTP.END_OF_BODY THEN
      UTL_HTTP.END_RESPONSE(l_http_response);
  END;
EXCEPTION
  WHEN OTHERS THEN

    DBMS_OUTPUT.PUT_LINE('EXCEPTION: '||SQLERRM);
    DBMS_OUTPUT.PUT_LINE('EXCEPTION: '||DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);

    DBMS_OUTPUT.PUT_LINE('EXCEPTION: '||UTL_HTTP.GET_DETAILED_SQLERRM);
    UTL_HTTP.END_RESPONSE(l_http_response);
END;

我们已经将提供的证书安装到了Oracle钱包中,并且我们在不同的客户端使用相同的代码也没有问题。
有什么想法吗?

第23行是您的身份验证: UTL_HTTP.SET_AUTHENTICATION(r => l_http_request, username => user_id_chr, PASSWORD => password_chr); 可能是用户名或密码错误吗? - Rusty
4个回答

4
您没有提及您的网络访问控制列表(ACL)授予权限,但在Oracle 11g中,您必须为您要连接的主机和要使用的钱包设置ACL。由于您没有提到获取“ORA-24247:访问控制列表(ACL)拒绝网络访问”的错误,我将假设该部分已正确设置。
钱包ACL定义了其位置并向用户授予钱包的权限。如果没有这些权限,即使您有正确的密码,Oracle也不会打开钱包并向Web服务器呈现证书。钱包ACL是使用以下PL / SQL作为SYS创建的:
BEGIN
    UTL_HTTP.ASSIGN_WALLET_ACL (
       acl          => 'your_acl_name.xdb',
       wallet_path  => '/path/to/my/wallet/');
END;
/

创建钱包ACL之后,用户必须被授予相应的权限。
BEGIN
    DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
        acl         => 'your_acl_name.xml',
        principal   => 'MY_USER',
        is_grant    =>  TRUE,
        privilege   => 'use-client-certificates');
END;
/

那将允许Oracle代表您的用户打开钱包并向Web服务器呈现证书。

这并没有提供问题的答案。如果要批评或请求作者澄清,请在他们的帖子下留言 - 您始终可以在自己的帖子上发表评论,并且一旦您拥有足够的声望,您将能够评论任何帖子 - m69 ''snarky and unwelcoming''
也许可以用更直接的措辞,但我提供了一个答案。首先,我解释了“致命SSL错误”很可能是Oracle没有呈现客户端证书造成的。其次,我解释了创建钱包ACL并授予用户特定权限将允许Oracle为该用户呈现钱包并消除该错误。最后,我提供了一种测试Oracle和Web服务器之间连接的快捷方式。需要重新以更积极的方式表达吗? - James Schrumpf
就目前而言,它看起来确实像是一系列问题、建议和评论的组合,而不是一个答案。最好重新以更具回答性的风格进行改写,这样至少可以避免被标记并删除为“非答案”。 - m69 ''snarky and unwelcoming''

4

您正在访问的网站可能通过过时的SSLv3协议阻止连接,同时,新的算法可能不受Oracle DB 11.2.0.3支持。

有一个已知的错误,但显然影响版本高达11.1:

使用TLSv1时,UTL_HTTP包失败并显示ORA-29273 ORA-28860(文档ID 727118.1) https://support.oracle.com/epmos/faces/DocContentDisplay?_afrLoop=842518171804826&id=727118.1&_afrWindowMode=0&_adf.ctrl-state=142oqbz21t_4

最近还有一个针对11.2.0.4的错误20323753已注册,尚未修复。可能与您的情况相同。


1

我想提供以下内容:

  1. 创建一个JAVA函数

    CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "HttpSSLGet"
    AS
    import java.net.URL;
    import java.io.*;
    import javax.net.ssl.HttpsURLConnection;
    public class HttpSSLGet
    {
      public static String GetSSL(final String url)
      {
        StringBuffer buffer = new StringBuffer();
        try
        {
          URL myUrl = new URL(url);
          HttpsURLConnection con = (HttpsURLConnection)myUrl.openConnection();
          InputStream ins = con.getInputStream();
          InputStreamReader isr = new InputStreamReader(ins);
          BufferedReader in = new BufferedReader(isr);
          String inputLine;
    
          while ((inputLine = in.readLine()) != null)
          {
            buffer.append(inputLine);
          }
          in.close();
        }
        catch (Exception e)
        {
          return buffer.toString() + "\n" + e.toString();
        }
        return buffer.toString();
      }
    }
    
  2. 创建一个PL/SQL包(独立函数)

    CREATE OR REPLACE PACKAGE PCK_HTTP AUTHID DEFINER
    AS
    
    function GetSSL(aUrl Varchar2) return Varchar2;
    
    END;
    /
    
    CREATE OR REPLACE PACKAGE BODY PCK_HTTP AS
    
    function GetSSL(aUrl Varchar2) return Varchar2 AS LANGUAGE JAVA
    NAME 'HttpSSLGet.GetSSL(java.lang.String) return java.lang.String';
    
    END;
    /
    
  3. Oracle内置的JAVA虚拟机存在问题。它包含的证书比标准的“独立”JAVA少。可能需要将下载的证书添加到内置的java虚拟机中(而不是独立的java),例如在命令行中(Windows):

    keytool -import -alias geos -keystore 
    "d:\Oracle\product\11.2.0\dbhome_1\javavm\lib\security\cacerts" 
    -file example.com.cer -storepass changeit
    
  4. 在查询或PL/SQL中使用函数,例如:

    SELECT PCK_HTTP.GetSSL('https://www.example.com') FROM DUAL
    

0
我们发现钱包中的旧证书虽然没有过期,但已经无法使用了。通过在新钱包中测试新证书,证实了这一点。将旧证书删除并将新证书添加到原始钱包中可以解决此问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接