使用PL/SQL从Oracle存储过程使用基于cookie的身份验证的SOAP web服务

使用PL/SQL从Oracle存储过程使用基于cookie的身份验证的SOAP web服务,oracle,web-services,cookies,soap,plsql,Oracle,Web Services,Cookies,Soap,Plsql,我们正试图直接从oracledb存储过程使用具有PL/SQL的安全(https)web服务。有一个单独的web服务用于用户操作(登录/注销)及其文档状态 成功登录后,将创建会话cookie。必须将Web服务客户端配置为接收cookie。登录后,后续调用将成功,只要它们包含登录时接收的会话cookie 但是,我们不知道如何存储和使用PL/SQL中的cookie。如有任何帮助,我们将不胜感激 注: 我们已成功创建Oracle电子钱包,将web服务的证书添加到电子钱包,并将其分配给请求,如下所示:

我们正试图直接从oracledb存储过程使用具有PL/SQL的安全(https)web服务。有一个单独的web服务用于用户操作(登录/注销)及其文档状态

成功登录后,将创建会话cookie。必须将Web服务客户端配置为接收cookie。登录后,后续调用将成功,只要它们包含登录时接收的会话cookie

但是,我们不知道如何存储和使用PL/SQL中的cookie。如有任何帮助,我们将不胜感激


注:

  • 我们已成功创建Oracle电子钱包,将web服务的证书添加到电子钱包,并将其分配给请求,如下所示:

    Declare
      ...
      v_req_context    UTL_HTTP.REQUEST_CONTEXT_KEY;
      ...
    Begin
      ...
      v_req_context := UTL_HTTP.CREATE_REQUEST_CONTEXT(wallet_path => 'file:'||ssl_cert_wallet_path,
                                                       wallet_password => ssl_cert_wallet_password);
      v_http_request := UTL_HTTP.BEGIN_REQUEST(url             => 'https://<url_to_webservice_wsdl>',
                                               method          => 'POST',
                                               http_version    => 'HTTP/1.1',
                                               request_context => v_req_context);
      ...
    End;
    
    Begin
      -- SOAP Authentication request parameters
      v_string_request := '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:examples:userService">
                             <soapenv:Header/>
                             <soapenv:Body>
                               <urn:' || v_service_operation || ' soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:urn="' || v_service_namespace || '/">
                                 <userId>' || p_username || '</userId>
                                 <password>' || p_password || '</password>
                                 <lang>' || p_lang || '</lang>
                               </urn:' || v_service_operation || '>
                             </soapenv:Body>
                           </soapenv:Envelope>';
    
      UTL_HTTP.SET_TRANSFER_TIMEOUT(60);
    
      v_http_request := UTL_HTTP.BEGIN_REQUEST(url             => v_host_name || ':' || v_port || v_service_posfix,
                                               method          => 'POST',
                                               http_version    => 'HTTP/1.1',
                                               request_context => v_req_context);
    
      UTL_HTTP.SET_HEADER(v_http_request, 'Host', v_host_name || ':' || v_port);
      UTL_HTTP.SET_HEADER(v_http_request, 'Connection', 'close');
      UTL_HTTP.SET_HEADER(v_http_request, 'Content-Type', 'text/xml;charset=UTF-8');
      UTL_HTTP.SET_HEADER(v_http_request, 'SOAPAction', '"' || v_service_operation || '"');
      UTL_HTTP.SET_HEADER(v_http_request, 'Content-Length', length(v_string_request));
    
      <<login_request_loop>>
      for i in 0..CEIL(LENGTH(v_string_request) / v_buffer_size) - 1
      loop
        v_substring_msg := SUBSTR(v_string_request, i * v_buffer_size + 1, v_buffer_size);
    
        begin
          v_raw_data := UTL_RAW.CAST_TO_RAW(c => v_substring_msg);
          UTL_HTTP.WRITE_RAW(r => v_http_request, data => v_raw_data);
        exception
          when NO_DATA_FOUND then EXIT login_request_loop;
        end;
      end loop login_request_loop;
    
      -- SOAP Authentication request
      v_http_response := UTL_HTTP.GET_RESPONSE(v_http_request);
      ...
    End;
    
    声明
    ...
    v_req_context UTL_HTTP.REQUEST_context_KEY;
    ...
    开始
    ...
    v_req_context:=UTL_HTTP.创建_请求_context(钱包路径=>'文件:'| | ssl证书_钱包路径,
    钱包密码=>ssl证书(钱包密码);
    v_http_请求:=UTL_http.BEGIN_请求(url=>https://),
    方法=>'POST',
    http_version=>http/1.1,
    请求上下文=>v\u请求上下文);
    ...
    结束;
    
  • 我们向用户服务提出如下请求:

    Declare
      ...
      v_req_context    UTL_HTTP.REQUEST_CONTEXT_KEY;
      ...
    Begin
      ...
      v_req_context := UTL_HTTP.CREATE_REQUEST_CONTEXT(wallet_path => 'file:'||ssl_cert_wallet_path,
                                                       wallet_password => ssl_cert_wallet_password);
      v_http_request := UTL_HTTP.BEGIN_REQUEST(url             => 'https://<url_to_webservice_wsdl>',
                                               method          => 'POST',
                                               http_version    => 'HTTP/1.1',
                                               request_context => v_req_context);
      ...
    End;
    
    Begin
      -- SOAP Authentication request parameters
      v_string_request := '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:examples:userService">
                             <soapenv:Header/>
                             <soapenv:Body>
                               <urn:' || v_service_operation || ' soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:urn="' || v_service_namespace || '/">
                                 <userId>' || p_username || '</userId>
                                 <password>' || p_password || '</password>
                                 <lang>' || p_lang || '</lang>
                               </urn:' || v_service_operation || '>
                             </soapenv:Body>
                           </soapenv:Envelope>';
    
      UTL_HTTP.SET_TRANSFER_TIMEOUT(60);
    
      v_http_request := UTL_HTTP.BEGIN_REQUEST(url             => v_host_name || ':' || v_port || v_service_posfix,
                                               method          => 'POST',
                                               http_version    => 'HTTP/1.1',
                                               request_context => v_req_context);
    
      UTL_HTTP.SET_HEADER(v_http_request, 'Host', v_host_name || ':' || v_port);
      UTL_HTTP.SET_HEADER(v_http_request, 'Connection', 'close');
      UTL_HTTP.SET_HEADER(v_http_request, 'Content-Type', 'text/xml;charset=UTF-8');
      UTL_HTTP.SET_HEADER(v_http_request, 'SOAPAction', '"' || v_service_operation || '"');
      UTL_HTTP.SET_HEADER(v_http_request, 'Content-Length', length(v_string_request));
    
      <<login_request_loop>>
      for i in 0..CEIL(LENGTH(v_string_request) / v_buffer_size) - 1
      loop
        v_substring_msg := SUBSTR(v_string_request, i * v_buffer_size + 1, v_buffer_size);
    
        begin
          v_raw_data := UTL_RAW.CAST_TO_RAW(c => v_substring_msg);
          UTL_HTTP.WRITE_RAW(r => v_http_request, data => v_raw_data);
        exception
          when NO_DATA_FOUND then EXIT login_request_loop;
        end;
      end loop login_request_loop;
    
      -- SOAP Authentication request
      v_http_response := UTL_HTTP.GET_RESPONSE(v_http_request);
      ...
    End;
    
    开始
    --SOAP身份验证请求参数
    v_字符串_请求:='
    “|| p|u用户名| |”
    “|| p|u密码| |”
    | | p|lang | |
    ';
    UTL_HTTP.设置_传输_超时(60);
    v|U http|U请求:=UTL|U http.BEGIN|U请求(url=>v|U主机名:“| v|U端口| v|U服务| posfix,
    方法=>'POST',
    http_version=>http/1.1,
    请求上下文=>v\u请求上下文);
    UTL_HTTP.SET_头(v_HTTP_请求,'Host',v_主机名| |':'| | v|端口);
    UTL_HTTP.SET_头(v_HTTP_请求,'Connection','close');
    UTL_HTTP.SET_头(v_HTTP_请求,'Content Type','text/xml;charset=UTF-8');
    UTL_HTTP.SET_头(v_HTTP_请求,'SOAPAction','''“| v|u服务| u操作| |'”);
    UTL_HTTP.SET_头(v_HTTP_请求,'内容长度',长度(v_字符串_请求));
    对于0..CEIL中的i(长度(v_字符串请求)/v_缓冲区大小)-1
    环
    v_substring_msg:=SUBSTR(v_string_请求,i*v_buffer_size+1,v_buffer_size);
    开始
    v_raw_data:=UTL_raw.CAST_TO_raw(c=>v_substring_msg);
    UTL_HTTP.WRITE_RAW(r=>v_HTTP_请求,data=>v_RAW_数据);
    例外
    当找不到数据时,退出登录请求循环;
    结束;
    结束循环登录\请求\循环;
    --SOAP身份验证请求
    v_http_response:=UTL_http.GET_response(v_http_请求);
    ...
    结束;
    

    • 让我把答案放在下面,以备将来使用:

      如果您尝试使用的web服务是安全(https)web服务,则不要在标头中单独设置主机。 如果删除以下行,代码的工作方式就像魅力一样:

      UTL_HTTP.SET_HEADER(v_http_request, 'Host', v_host_name || ':' || v_port);
      

      PS:我自己发现的,所以我无法参考任何来源。

      您确定需要手动处理cookie吗?表示只要后续调用在同一数据库会话中,Cookie就会由UTL_HTTP自动管理。如果您确实需要cookie操作,同一个文档应该会给您一个开始。我们尝试在调用登录函数后使用主要操作,但没有办法,也没有起作用。。