Добрый день!
Прорабатываем у себя возможность реализация автоматизированного мониторинга клиентской базы на наличие информации о банкротстве клиента с использованием веб-сервиса ЕФРСБ и обращения к нему через запросы напрямую из Oracle. На текущем этапе успешно проходим digest авторизацию, но на отправку xml запроса методом POST получаем ответ:
Цитата:Response status:500
Reason phrase :Internal Server Error
HTTP Version :HTTP/1.1
Пример xml запроса взяли из инструкции, отредактировав только дату:
Цитата:<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetMessageIds xmlns="http://tempuri.org/">
<startDate>2020-11-23T00:00:00</startDate>
<endDate xsi:nil="true"/>
</GetMessageIds>
</s:Body>
</s:Envelope>
Ссылку по которой отправляем POST запрос взяли из
инструкции.
Тестовый логин и пароль используем согласно инструкции.
Полный запрос из Oracle ниже.
declare
--
sLogin Varchar2(15) := 'demowebuser';
sPassword Varchar2(15) := 'Ax!761BN';
sUrl Varchar2(254) := 'https://services.fedresurs.ru/Bankruptcy/MessageServiceDemo/WebService.svc';
sRequest Varchar2(32000);
sResponse clob;
sProfile Varchar2(254);
nProfile number(1);
sRequestOriginal Varchar2(32000);
l_authenticate_message varchar2(500);
--Предварительная иницилизация
procedure https_init is
begin
-- We can read the Wallet without a password, which is enough to use the trusted certificates in there.
--
utl_http.set_wallet('file:C:\dstr\Oracle\bin\owm\wallets\User1\','Test1234');
utl_http.set_detailed_excp_support (enable => true);
utl_http.set_response_error_check (enable => false);
utl_http.set_persistent_conn_support (true, 10);
utl_http.set_follow_redirect(0);
--
--Set it to use a proxy to reach the outside world
--
--utl_http.set_proxy('http://*********');
--
end https_init;
--
-- MD5
--
function digest_auth_md5_calcs
(i_username in varchar2, i_password in varchar2, i_req_path in varchar2,
i_realm in varchar2, i_server_nonce in varchar2,
i_qop in varchar2 default 'auth',
i_client_nonce in varchar2 default '0a4f113b',
i_req_type in varchar2 default 'GET', i_req_cnt IN NUMBER default 1)
return varchar2 is
--
v_in_str varchar2(2000);
v_in_raw raw(2000);
v_out varchar2(60);
--
v_ha1 varchar2(40);
v_ha2 varchar2(40);
v_response varchar2(40);
--
begin
--
v_in_str := i_username||':'||i_realm||':'||i_password;
v_in_raw := utl_raw.cast_to_raw(v_in_str);
v_out := DBMS_OBFUSCATION_TOOLKIT.md5(input => v_in_raw);
v_ha1 := lower(v_out);
--
v_in_str := i_req_type||':'||i_req_path;
v_in_raw := utl_raw.cast_to_raw(v_in_str);
v_out := DBMS_OBFUSCATION_TOOLKIT.md5(input => v_in_raw);
v_ha2 := lower(v_out);
--
v_in_str := v_ha1||':'||i_server_nonce||':'||lpad(i_req_cnt,8,0)||':'||i_client_nonce||':'||i_qop||':'||v_ha2;
v_in_raw := utl_raw.cast_to_raw(v_in_str);
v_out := DBMS_OBFUSCATION_TOOLKIT.md5(input => v_in_raw);
v_response := lower(v_out);
--
return v_response;
end digest_auth_md5_calcs;
--
-- Извлечение переменных из ответа от веб-сервиса
--
procedure extract_auth_items
(i_text in varchar2,
o_realm out varchar2, o_qop out varchar2, o_nonce out varchar2, o_opaque out varchar2) is
begin
o_realm := substr(regexp_substr(i_text, 'realm="[^"]+' ),8);
o_qop := substr(regexp_substr(i_text, 'qop="[^"]+' ),6);
o_nonce := substr(regexp_substr(i_text, 'nonce="[^"]+' ),8);
o_opaque := substr(regexp_substr(i_text, 'opaque="[^"]+'),9);
end extract_auth_items;
--
-- Авторизация
--
procedure auth_digest
(io_http_request in out UTL_HTTP.REQ, i_auth_value in varchar2,
i_username in varchar2, i_password in varchar2,
i_req_path in varchar2, i_qop in varchar2 default 'auth',
i_req_cnt in number default 1, i_client_nonce in varchar2 default null,
i_value out varchar2)
is
l_realm varchar2(400);
l_qop varchar2(30);
l_server_nonce VARCHAR2(400);
l_opaque varchar2(100);
--
l_response varchar2(40);
--
l_client_nonce varchar2(30);
--
begin
--
-- Получаем данные для Digest авторизации
--
extract_auth_items (i_auth_value,
l_realm, l_qop, l_server_nonce, l_opaque);
--
IF i_client_nonce is not null then
l_client_nonce := i_client_nonce;
ELSE
l_client_nonce := lower(utl_raw.cast_to_raw(DBMS_OBFUSCATION_TOOLKIT.md5(input_string=>dbms_random.value)));
END IF;
--
l_response := digest_auth_md5_calcs
(i_username => i_username, i_password => i_password, i_req_path => i_req_path,
i_realm => l_realm, i_server_nonce => l_server_nonce,
i_client_nonce => l_client_nonce, i_req_type => 'POST');
--
i_value := 'Digest username="' ||i_username ||'",'||
' realm="' ||l_realm ||'",'||
' nonce="' ||l_server_nonce ||'",'||
' uri="' ||i_req_path ||'",'||
' response="' ||l_response ||'",'||
' qop=' ||i_qop ||',' ||
' nc=' ||lpad(i_req_cnt,8,0) ||',' ||
' cnonce="' ||i_client_nonce ||'"'
;
--
IF l_opaque is not null then
i_value := i_value||',opaque="'||l_opaque||'"';
END IF;
dbms_output.put_line('dbms_output = '||$$plsql_unit||' line ='||$$plsql_line || '. DBMS: i_value : ' || i_value ||'');
end auth_digest;
-- Текст ответа по тегам
procedure dump_resp (i_http_resp in UTL_HTTP.RESP) is
begin
dbms_output.put_line('-------Response-------');
dbms_output.put_line('Response status:'||i_http_resp.status_code);
dbms_output.put_line('Reason phrase :'||i_http_resp.reason_phrase);
dbms_output.put_line('HTTP Version :'||i_http_resp.http_version);
dbms_output.put_line('-----End Response-----');
end dump_resp;
-- Текст заголовка
procedure dump_hdr (io_http_resp in out UTL_HTTP.RESP) is
l_name VARCHAR2(256);
l_value VARCHAR2(1024);
begin
dbms_output.put_line('-----Headers -----');
FOR i IN 1..UTL_HTTP.GET_HEADER_COUNT(io_http_resp) LOOP
UTL_HTTP.GET_HEADER(io_http_resp, i, l_name, l_value);
DBMS_OUTPUT.PUT_LINE(l_name || ': ' || l_value);
END LOOP;
dbms_output.put_line('-----End Headers -----');
end dump_hdr;
-- Текст тела
procedure dump_body_txt (io_http_resp in out UTL_HTTP.RESP) is
l_name VARCHAR2(256);
l_value VARCHAR2(32000);
begin
dbms_output.put_line('-----Body-----');
LOOP
utl_http.read_line(io_http_resp, l_value, TRUE);
dbms_output.put_line(l_value);
END LOOP;
exception
when UTL_HTTP.END_OF_BODY then
dbms_output.put_line('----End Body----');
end dump_body_txt;
--
procedure get_xxx (i_username in varchar2, i_password in varchar2, p_Url in Varchar2 default null, p_Soap_Text in Varchar2 default null)
is
l_server varchar2(50) := 'https://services.fedresurs.ru';
l_method varchar2(100) := '/Bankruptcy/MessageServiceDemo/WebService.svc';
cAction constant varchar2(100) := '"http://www.w3.org/2001/XMLSchema"';
--
l_http_request UTL_HTTP.REQ;
l_http_response UTL_HTTP.RESP;
--
l_name VARCHAR2(256);
l_value VARCHAR2(1024);
l_ind NUMBER;
l_max NUMBER;
l_blob BLOB;
--
l_Soap_Text Varchar2(32000);
l_Url Varchar2(256);
begin
https_init;
l_Soap_Text := p_Soap_Text;
if length(nvl(p_Url,'')) > 0 then
l_Url := p_Url;
else
l_Url := l_server||l_method;
end if;
l_Soap_Text := convert(p_Soap_Text, 'UTF8');
l_http_request := utl_http.begin_request(l_Url, 'POST','HTTP/1.1');
--l_http_request := utl_http.begin_request(l_Url);
utl_http.set_body_charset(l_http_request, 'UTF-8');
utl_http.set_header(l_http_request, 'Content-Type', 'text/xml');
utl_http.set_header(l_http_request, 'SOAPAction', cAction);
utl_http.set_header(l_http_request, 'Content-Length', lengthc(l_Soap_Text));
utl_http.set_header(l_http_request, 'Connection', 'Keep-Alive');
utl_http.write_text(l_http_request, l_Soap_Text);
l_http_response := utl_http.get_response(l_http_request);
dump_resp (l_http_response);
dump_hdr (l_http_response);
if l_http_response.status_code = utl_http.HTTP_UNAUTHORIZED then
utl_http.get_header_by_name(l_http_response, 'WWW-Authenticate', l_value, 1);
utl_http.end_response(l_http_response);
if substr(l_value,1,6) = 'Digest' then
l_http_request := UTL_HTTP.BEGIN_REQUEST(l_Url);
auth_digest (io_http_request => l_http_request, i_auth_value => l_value,
i_username => nvl(i_username,'xxxx'), i_password => nvl(i_password,'xxxx'), i_req_path => l_method,
i_client_nonce => 'f398a414e3efc2ad', i_value => l_authenticate_message);
--l_http_request:= utl_http.begin_request(l_Url);
l_http_request:= utl_http.begin_request(l_Url, 'POST','HTTP/1.1');
utl_http.set_body_charset(l_http_request, 'UTF-8');
utl_http.set_header(l_http_request, 'Content-Type', 'text/xml;charset=UTF-8');
utl_http.set_header(l_http_request, 'SOAPAction', cAction);
utl_http.set_header(l_http_request, 'Content-Length', lengthc(l_Soap_Text));
utl_http.set_header(l_http_request, 'Connection', 'Close');
utl_http.set_header(l_http_request, 'Authorization', l_authenticate_message);
utl_http.write_text(l_http_request, l_Soap_Text);
l_http_response := utl_http.get_response(l_http_request);
dump_resp (l_http_response);
dump_hdr (l_http_response);
end if;
end if;
dump_body_txt (l_http_response);
UTL_HTTP.END_RESPONSE(l_http_response);
exception
when others then
UTL_HTTP.END_RESPONSE(l_http_response);
end get_xxx;
--
begin
sRequest :='<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetMessageIds xmlns="http://tempuri.org/">
<startDate>2020-11-23T00:00:00</startDate>
<endDate xsi:nil="true"/>
</GetMessageIds>
</s:Body>
</s:Envelope>';
get_xxx(sLogin, sPassword, sUrl, sRequest);
dbms_output.put_line('dbms_output = '||$$plsql_unit||' line ='||$$plsql_line || '. DBMS: sResponse : ' || sResponse ||'');
end;
Лог обработки запроса:
-------Response-------
Response status:401
Reason phrase :Access Denied
HTTP Version :HTTP/1.1
-----End Response-----
-----Headers -----
Server: nginx
Date: Mon, 30 Nov 2020 12:34:05 GMT
Content-Type: text/html
Content-Length: 1292
Connection: keep-alive
WWW-Authenticate: Digest realm="https://services.fedresurs.ru/Bankruptcy/MessageServiceDemo/WebService.svc", nonce="/5y8NvlF2kSMihUvfeg5Ng==", opaque="7bFirCaiZEKBqmAp2MttQw==", stale=false, algorithm="MD5", qop="auth"
X-Powered-By: ASP.NET
-----End Headers -----
dbms_output = line =130. DBMS: i_value : Digest username="demowebuser", realm="https://services.fedresurs.ru/Bankruptcy/MessageServiceDemo/WebService.svc", nonce="/5y8NvlF2kSMihUvfeg5Ng==", uri="/Bankruptcy/MessageServiceDemo/WebService.svc", response="1fa315961ca983ca1c58f55370003bd4", qop=auth, nc=00000001, cnonce="f398a414e3efc2ad",opaque="7bFirCaiZEKBqmAp2MttQw=="
-------Response-------
Response status:500
Reason phrase :Internal Server Error
HTTP Version :HTTP/1.1
-----End Response-----
-----Headers -----
Server: nginx
Date: Mon, 30 Nov 2020 12:34:05 GMT
Content-Type: text/xml; charset=utf-8
Content-Length: 274
Connection: close
Cache-Control: private
Set-Cookie: ASP.NET_SessionId=ssyhiqeuvh4eq3ir03yzf0lo; path=/; HttpOnly; SameSite=Lax
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
-----End Headers -----
-----Body-----
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode>s:Client</faultcode><faultstring xml:lang="ru-RU">В процессе обработки запроса произошла ошибка.</faultstring></s:Fault></s:Body></s:Envelope>
----End Body----
dbms_output = line =262. DBMS: sResponse :
Вопросы:
1. С чем может быть связана проблема, что не так с запросом?
2. Есть ли готовые решения работы с сервисом из Oracle? Есть клиенты которые уже работают с сервисом напрямую из Oracle, без использования "ПО посредников"?
Отредактировано пользователем 30 ноября 2020 г. 16:41:09(UTC)
| Причина: Не указана