Problem z połączeniem sie do WebService serwisu Puesc

0

Cześć, Piszę prostą aplikację do wymiany informacji z PUESC. Niestety utknąłem na próbie skomunikowania się z PUESC-em. Co ciekawe, skonfigurowane SoapUI bez problemu łączy się z serwisem. Mój kod jest w Pythonie (z góry przepraszam za jego jakość), ale jak widać https://4programmers.net/Forum/C_i_.NET/290661-laczenie_sie_z_webservice_seap_w_puesc problem jest szerszy.

Co do tej pory udało mi się ustalić:

  • Jeśli szybko "przekleję" wygenerowany przez Soap UI request do mojego kodu w pythonie(w miejsce xmla)
    to serwis odpowiada poprawnie
  • Podejrzewam że problem leży w generowaniu UsernameToken lub MessageID
  • Support PUESC olewa temat

Może ktoś z Was ma jakiś pomysł gdzie lezy problem? Albo udało mu się rozwiązać problem w innym języku.

Poniżej link do dokumentacji usługi:
https://puesc.gov.pl/documents/20123/603192553/PUESCKUD_SEAP_XML_PL.pdf/1553ee91-140b-56f3-d9e1-fc1bb1d39220?t=1623411653806

import base64
import hashlib
import json
import secrets
import uuid
from datetime import datetime
import pytz
import requests
from requests.structures import CaseInsensitiveDict
from xml.dom import minidom


def load_credentials(filename):
    with open(filename, "r") as file:
        return json.load(file)


def generate_nonce(size=16):
    return secrets.token_bytes(size)


def sha1_base64(data):
    return base64.b64encode(hashlib.sha1(data).digest()).decode("utf-8")


def construct_password_digest(nonce, created, password):
    password_sha1_base64 = sha1_base64(password.encode("utf-8"))
    data_to_digest = (
        nonce + created.encode("utf-8") + password_sha1_base64.encode("utf-8")
    )
    return sha1_base64(data_to_digest)


def prepare_soap_request(url, headers, login, password, nonce, created_date):
    message_id = f"uuid:{uuid.uuid4()}"
    user_name_token = f"UsernameToken-{uuid.uuid4()}"

    password_digest_base64_encoded = construct_password_digest(
        nonce, created_date, password
    )
    nonce_base64_encoded = base64.b64encode(nonce).decode("utf-8")

    xml = f"""
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                      xmlns:_v2="http://www.mf.gov.pl/uslugiBiznesowe/WsPull/Usluga/2014/01_v2_0">
        <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
            <wsse:Security soapenv:mustUnderstand="1"
                xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <wsse:UsernameToken wsu:Id="{user_name_token}">
                    <wsse:Username>{login}</wsse:Username>
                    <wsse:Password
                        Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
                        {password_digest_base64_encoded}</wsse:Password>
                    <wsse:Nonce
                        EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
                        {nonce_base64_encoded}</wsse:Nonce>
                    <wsu:Created>{created_date}</wsu:Created>
                </wsse:UsernameToken>
            </wsse:Security>
            <wsa:Action soapenv:mustUnderstand="1">GetNextDocument</wsa:Action>
            <wsa:MessageID soapenv:mustUnderstand="1">{message_id}</wsa:MessageID>
        </soapenv:Header>
        <soapenv:Body>
            <_v2:GetNextDocumentRequest>
            </_v2:GetNextDocumentRequest>
        </soapenv:Body>
    </soapenv:Envelope>
    """

    response = requests.post(url, headers=headers, data=xml)
    return response


if __name__ == "__main__":
    credentials = load_credentials("env.json")
    login = credentials["login"]
    password = credentials["password"]

    nonce = generate_nonce()
    created_date = datetime.now(pytz.timezone("UTC")).strftime("%Y-%m-%dT%H:%M:%SZ")

    url = "https://te-ws.puesc.gov.pl/seap_wsChannel/DocumentHandlingPort"
    headers = CaseInsensitiveDict()
    headers["Content-Type"] = "text/xml;charset=UTF-8"
    headers["SOAPAction"] = "GetNextDocument"

    response = prepare_soap_request(url, headers, login, password, nonce, created_date)
    xml_pretty = minidom.parseString(response.text).toprettyxml()
    print(xml_pretty)



Przykładowa odpowiedź serwisu generowana po wywołaniu kodu powyżej:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Header>
                <Action xmlns="http://www.w3.org/2005/08/addressing">http://www.mf.gov.pl/uslugiBiznesowe/WsPull/Usluga/2014/01_v2_0/DocumentHandlingPort/GetNextDocument/Fault/WSSecurityException</Action>
                <MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:614444538-33df-48bc-afc4-6459039e1a31</MessageID>
                <To xmlns="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</To>
                <RelatesTo xmlns="http://www.w3.org/2005/08/addressing">uuid:0bbeb7c0-ba33-43be-9407-03ffce97b121</RelatesTo>
        </soap:Header>
        <soap:Body>
                <soap:Fault>
                        <faultcode xmlns:ns1="http://ws.apache.org/wss4j">ns1:SecurityError</faultcode>
                        <faultstring>A security error was encountered when verifying the message</faultstring>
                </soap:Fault>
        </soap:Body>
</soap:Envelope>

Poniżej odpowiedź generowana po zapytaniu przez Soap UI:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Header>
      <Action xmlns="http://www.w3.org/2005/08/addressing">http://www.mf.gov.pl/uslugiBiznesowe/WsPull/Usluga/2014/01_v2_0/DocumentHandlingPort/GetNextDocumentResponse</Action>
      <MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:6ac7d983-62f5-4ba9-a390-d16596d5ac0d</MessageID>
      <To xmlns="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</To>
      <RelatesTo xmlns="http://www.w3.org/2005/08/addressing">uuid:d4533c17-81f0-4039-b7a7-ba1466582c37</RelatesTo>
   </soap:Header>
   <soap:Body>
      <ns2:GetNextDocumentResponse hasNext="false" xmlns="http://www.mf.gov.pl/schematy/SISC/WsChannel/2014/01_v2_0" xmlns:ns2="http://www.mf.gov.pl/uslugiBiznesowe/WsPull/Usluga/2014/01_v2_0"/>
   </soap:Body>
</soap:Envelope>
1

Wygląda jakby login albo hasło leciało źle lub może idzie, ale ma niepoprawne wartości. Najlepiej jak odpalisz ten skrypt w Pythonie i przechwycisz request z autoryzacją, który leci. Jeśli to aplikacja przeglądarkowa to wystarczą narzędzia developerskie przeglądarki - zakładka sieć.
Ewentualnie możesz odpalić program Wireshark, strzelić skryptem Pythona i zobaczyć co poszło w requście.

Podobny temat: https://taxfree.pl/ufaqs/blad-500-ns1securityerror/

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.