如何在 PL/SQL SOAP WSDL 网络服务调用中指定基本身份验证

How to specify basic authentication in PL/SQL SOAP WSDL web service call

我正在尝试使用 PL/SQL 从 Oracle Applications EBS 服务器调用 Oracle Fusion Cloud Web 服务。我可以从 SOAPUI 成功执行 Web 服务调用,但是在 SOAPUI 中,身份验证(基本身份验证)是在单独的 window 中指定的。我的意图是使用来自 SOAPUI 的工作 SOAP 信封,但是如何在 PL/SQL (Oracle 11g) 中指定 Web 服务基本身份验证?

从 google 看来,基本身份验证可以包含在 SOAP 信封的 header 中。但是,所有示例都引用了 http://docs.oasis-open.org,这是一个我不知道是否可以信任的网站,尤其是当它使用 http 并且需要 PasswordText 作为其 url 的一部分时.看这个例子:

<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken wsu:Id="UsernameToken-9419978" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>admin</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">admin</wsse:Password></wsse:UsernameToken></wsse:Security>
</soapenv:Header>

dba 还必须设置一个 ACL 和一个钱包(没有密码)。

我现在的密码是:

create or replace PROCEDURE p_soap_request(p_username IN VARCHAR2, p_password IN VARCHAR2
--, p_proxy IN VARCHAR2
) IS
    soap_request  VARCHAR2(30000);
    soap_respond  CLOB;
    http_req      utl_http.req;
    http_resp     utl_http.resp;
    resp          XMLType;
    soap_err      exception;
    v_code        VARCHAR2(200);
    v_msg         VARCHAR2(1800);
    v_len number;
    v_txt Varchar2(32767);
  BEGIN
    -- UTL_HTTP.SET_PROXY(p_proxy);
    -- Define the SOAP request according the the definition of the web service being called
    soap_request:= '<?xml version = "1.0" encoding = "UTF-8"?>'||
                   '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">'||
                   '  <SOAP-ENV:Body>'||
                   '    <m:DownloadRequest xmlns:m="http://www.website.net/messages/GetDetails">'||
                   '      <m:UserName>'||p_username||'</m:UserName>'||
                   '      <m:Password>'||p_password||'</m:Password>'||
                   '    </m:DownloadRequest>'||
                   '  </SOAP-ENV:Body>'||
                   '</SOAP-ENV:Envelope>';

    http_req:= utl_http.begin_request
              ( 'http://www.website.net/webservices/GetDetailsService.asmx'
              , 'POST'
              , 'HTTP/1.1'
              );
    utl_http.set_header(http_req, 'Content-Type', 'text/xml');
    utl_http.set_header(http_req, 'Content-Length', length(soap_request));
    utl_http.set_header(http_req, 'Download', ''); -- header requirements of particular web service
    utl_http.write_text(http_req, soap_request);
    http_resp:= utl_http.get_response(http_req);
    utl_http.get_header_by_name(http_resp, 'Content-Length', v_len, 1); -- Obtain the length of the response
    FOR i in 1..CEIL(v_len/32767) -- obtain response in 32K blocks just in case it is greater than 32K
    LOOP
        utl_http.read_text(http_resp, v_txt, case when i < CEIL(v_len/32767) then 32767 else mod(v_len,32767) end);
        soap_respond := soap_respond || v_txt; -- build up CLOB
    END LOOP;
    utl_http.end_response(http_resp);
    resp:= XMLType.createXML(soap_respond); -- Convert CLOB to XMLTYPE
  END;

我不确定用什么替换我的服务器的 <m:DownloadRequest xmlns:m="http://www.website.net/messages/GetDetails">。也不确定如何指定钱包。

我的 SOAPUI 信封是:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://xmlns.oracle.com/apps/financials/commonModules/shared/model/erpIntegrationService/types/">
   <soapenv:Header/>
   <soapenv:Body>
      <typ:submitESSJobRequest>
         <typ:jobPackageName>/oracle/apps/ess/financials/commonModules/shared/common/interfaceLoader</typ:jobPackageName>                             
         <typ:jobDefinitionName>InterfaceLoaderController</typ:jobDefinitionName>
         <!--Zero or more repetitions:-->
<typ:paramList>15</typ:paramList><!--GL Costing-->
<typ:paramList>17518</typ:paramList><!--UCM File Number-->
<typ:paramList>N</typ:paramList>
<typ:paramList>N</typ:paramList>
<typ:paramList>#NULL</typ:paramList>
      </typ:submitESSJobRequest>
   </soapenv:Body>
</soapenv:Envelope>

SOAP WSDL url 是:

https://your.domain.fin.region.oraclecloud.com:443/publicFinancialCommonErpIntegration/ErpIntegrationService?WSDL

终于可以使用这段代码了:

declare
l_envelope       varchar2(32767);
l_http_request   utl_http.req;
l_http_response  utl_http.resp;
begin 
   utl_http.set_wallet
   (
      'file:/oracle/db/11.2.0/admin/EBST/wallet'
      ,'walletpassword'
   );
   l_envelope := '<?xml version="1.0"?>
   <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://xmlns.oracle.com/apps/financials/commonModules/shared/model/erpIntegrationService/types/">
   <soapenv:Header/>
   <soapenv:Body>
      <typ:submitESSJobRequest>
         <typ:jobPackageName>/oracle/apps/ess/financials/commonModules/shared/common/interfaceLoader</typ:jobPackageName>                             
         <typ:jobDefinitionName>InterfaceLoaderController</typ:jobDefinitionName>
         <!--Zero or more repetitions:-->
<typ:paramList>15</typ:paramList><!--GL Costing-->
<typ:paramList>17518</typ:paramList><!--UCM File Number-->
<typ:paramList>N</typ:paramList>
<typ:paramList>N</typ:paramList>
<typ:paramList>#NULL</typ:paramList>
      </typ:submitESSJobRequest>
   </soapenv:Body>
</soapenv:Envelope>';
   -- dbms_output.put_line(l_envelope);
   l_http_request := utl_http.begin_request
   (
      'https://username:password@yourdomain.com:443/publicFinancialCommonErpIntegration/ErpIntegrationService?WSDL', 
      'POST', 
      'HTTP/1.1'
   );
   utl_http.set_header(l_http_request, 'Content-Type', 'text/xml');
   utl_http.set_header(l_http_request, 'Content-Length', length(l_envelope));
   utl_http.set_header(l_http_request, 'SOAPAction', 'http://xmlns.oracle.com/apps/financials/commonModules/shared/model/erpIntegrationService/submitESSJobRequest');
   utl_http.write_text(l_http_request, l_envelope);
   l_http_response := utl_http.get_response(l_http_request);
   utl_http.read_text(l_http_response, l_envelope);
   utl_http.end_response(l_http_response); 
end;