使用PL/SQL从Oracle存储过程使用基于cookie的身份验证的SOAP web服务
我们正试图直接从oracledb存储过程使用具有PL/SQL的安全(https)web服务。有一个单独的web服务用于用户操作(登录/注销)及其文档状态 成功登录后,将创建会话cookie。必须将Web服务客户端配置为接收cookie。登录后,后续调用将成功,只要它们包含登录时接收的会话cookie 但是,我们不知道如何存储和使用PL/SQL中的cookie。如有任何帮助,我们将不胜感激使用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服务的证书添加到电子钱包,并将其分配给请求,如下所示:
注:
- 我们已成功创建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操作,同一个文档应该会给您一个开始。我们尝试在调用登录函数后使用主要操作,但没有办法,也没有起作用。。