Avatar billede seeque Nybegynder
27. april 2012 - 14:44 Der er 1 kommentar og
1 løsning

Generering af et signeret SOAP kald

Hej

Jeg står og skal gøre brug af en SOAP webservice som er lidt ud over det sædvanlige. Det er en opkobling mod Dansk Motor Register (DMR)
Samtlige kald jeg har prøvet at lave med standart SOAP kald via PHP fejler også selv om jeg prøver at sende certificatet med i headers.

Mit problem er at jeg skal have indsat en security-header som skal indeholde en signering af både timestamp og selve indholdet.
JEg har et PKCS12 test certificat som jeg udemærket skan læse og trækker selve certificatet og privatekey ud af, men når jeg bruger PHP's indbyggede certificering får jeg bare en valideringsfejl tilbage

Reference: #wsu-Timestamp does not validate.

Den XML som jeg skal generer skal ligne dette:
(alle data er testdata)

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
        <SOAP-ENV:Header>
                <wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1">
                        <wsu:Timestamp
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="wsu-Timestamp">

<wsu:Created>2012-04-26T06:46:06Z</wsu:Created>

<wsu:Expires>2012-04-26T06:51:06Z</wsu:Expires>
                        </wsu:Timestamp>
                        <wsse:BinarySecurityToken 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" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="wsse-BinarySecurityToken">MIIE/jCCBGegAwIBAgIEQDfJZDANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMSIwIAYDVQQDExlUREMgT0NFUyBTeXN0ZW10ZXN0IENBIElJMB4XDTExMDMwNzA5NDQyNVoXDTEzMDMwNzEwMTQyNVoweTELMAkGA1UEBhMCREsxIjAgBgNVBAoTGURBTklEIEEvUyAvLyBDVlI6MzA4MDg0NjAxRjAdBgNVBAMTFkRBTklEIEEvUyAtIERhbklEIFRlc3QwJQYDVQQFEx5DVlI6MzA4MDg0NjAtVUlEOjEyMzc1NTI4MDQ5OTcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMc9KcjHwg/IEMWoNkg9vLGIrd/KQrF8dVaviKMCmCv6k7UIQctKVr9G7jj1o2tXWnImq7dhNcnuOO2oI8V/g9BnywpznUoGuKu8fmlXzryBLqK7V1maLIQom2mzJObFR6aLkJO1VCnBOIkFPunQ5Qfz1aVtx9xvi9O7Bk+WUiXJAgMBAAGjggLLMIICxzAOBgNVHQ8BAf8EBAMCA7gwKwYDVR0QBCQwIoAPMjAxMTAzMDcwOTQ0MjVagQ8yMDEzMDMwNzEwMTQyNVowRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vdGVzdC5vY3NwLmNlcnRpZmlrYXQuZGsvb2NzcC9zdGF0dXMwggEDBgNVHSAEgfswgfgwgfUGCSkBAQEBAQEBAzCB5zAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5jZXJ0aWZpa2F0LmRrL3JlcG9zaXRvcnkwgbMGCCsGAQUFBwICMIGmMAoWA1REQzADAgEBGoGXVERDIFRlc3QgQ2VydGlmaWthdGVyIGZyYSBkZW5uZSBDQSB1ZHN0ZWRlcyB1bmRlciBPSUQgMS4xLjEuMS4xLjEuMS4xLjEuMy4gVERDIFRlc3QgQ2VydGlmaWNhdGVzIGZyb20gdGhpcyBDQSBhcmUgaXNzdWVkIHVuZGVyIE9JRCAxLjEuMS4xLjEuMS4xLjEuMS4zLjAXBglghkgBhvhCAQ0EChYIb3JnYW5XZWIwIAYDVR0RBBkwF4EVc3VwcG9ydEBjZXJ0aWZpa2F0LmRrMIGXBgNVHR8EgY8wgYwwV6BVoFOkUTBPMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMSIwIAYDVQQDExlUREMgT0NFUyBTeXN0ZW10ZXN0IENBIElJMQ4wDAYDVQQDEwVDUkwyNjAxoC+gLYYraHR0cDovL3Rlc3QuY3JsLm9jZXMuY2VydGlmaWthdC5kay9vY2VzLmNybDAfBgNVHSMEGDAWgBQcmAlHGkw4uRDFBClb8fROgGrMfjAdBgNVHQ4EFgQUuFTJ/nE9jaKj5SAUgw8J2XXGD88wCQYDVR0TBAIwADAZBgkqhkiG9n0HQQAEDDAKGwRWNy4xAwIDqDANBgkqhkiG9w0BAQUFAAOBgQBbreDzsmcDPG88FiWsaBrxZSX1nu3RIsEJ50DK2HZRPY/Y/6KHnl3N3SNJ0M2c+1HE1ej/skoxSV+ziec1qOMS5Pd1asWF8gb0iuvuf0A4PtoiNOkjLxzExtQkorn2H7XIwqqBwgJZIQ7JBmGLEuX3JOQhMtWHxhram0qWvWJqVA==</wsse:BinarySecurityToken>
                        <ds:Signature
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                                <ds:SignedInfo>
                                        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
                                        <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
                                        <ds:Reference URI="#SOAP-ENV-Body">
                                                <ds:Transforms>
                                                        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
                                                </ds:Transforms>
                                                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
                                                <ds:DigestValue>MhOai3
+fLd4koWrVvo3r686XtZU=</ds:DigestValue>
                                        </ds:Reference>
                                        <ds:Reference URI="#wsu-Timestamp">
                                                <ds:Transforms>
                                                        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
                                                </ds:Transforms>
                                                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>

<ds:DigestValue>fB1k8xmUNncOCqgBVzbzbmY6C28=</ds:DigestValue>
                                        </ds:Reference>
                                </ds:SignedInfo>

<ds:SignatureValue>OJAGoJ42jHPIjVuTmk8dPYKAgHY1G0OEu2ti9A0q6EXJn1QVy
+LYn60/2LptU4G75VMekE12e0U3PYZFbI3pTjSraBYXav5jWdTDZO5U970gdF3XsiTpovz9Q
+CPkQcIdmLaE22vWdEWs06HVB6Y0/+YQ6rHpDfqGruLs8rDcgbQ=</ds:SignatureValue>
                                <ds:KeyInfo>
                                        <wsse:SecurityTokenReference>
                                                <wsse:Reference URI="#wsse-BinarySecurityToken"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"></wsse:Reference>
                                        </wsse:SecurityTokenReference>
                                </ds:KeyInfo>
                        </ds:Signature>
                </wsse:Security>
        </SOAP-ENV:Header>
        <SOAP-ENV:Body
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SOAP-ENV-Body">
                <ns1:USKoeretoejRegistreringSekundaerErhvervListeHent_I
xmlns:ns1="http://skat.dk/dmr/2007/05/31/">
                        <ns2:HovedOplysninger xmlns:ns2="http://rep.oio.dk/skat.dk/basis/kontekst/xml/schemas/2006/09/01/">

<ns2:TransaktionIdentifikator>AZ123456</ns2:TransaktionIdentifikator>

<ns2:TransaktionTid>2012-04-26T06:46:06Z</ns2:TransaktionTid>
                        </ns2:HovedOplysninger>

<ns1:RegistreringNummerNummer>AZ123456</ns1:RegistreringNummerNummer>

</ns1:USKoeretoejRegistreringSekundaerErhvervListeHent_I>
        </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


Hvis flere point eller flere oplysninger kan hjælpe på svarene så sig endelig til så jeg om muligt kan give jer det ;-)

Mvh
Casper
Avatar billede seeque Nybegynder
02. maj 2012 - 15:29 #1
Fandt selv svaret.

Jeg skulle have fat i PHP's "openssl_pkcs12_read" og "openssl_pkey_export" samt en "XMLSecurityKey"-klasse
Det sammen med en nedarvning/overskrifning af soap klientens "__doRequest" gjorde at jeg fik hul igennem.

Hvis der skal uddybes mere for eventuelt interesserede så må i jo lige selv sige til ;-)
Avatar billede seeque Nybegynder
18. marts 2014 - 08:46 #2
Til andre som slås med DMR, så kan jeg ikke komme på hele løsningen da den er brugt på mit arbejde, men jeg kan komme med de ting som løste vores problemer med DMR's obskure signering....


Først har jeg fået lavet PHP-klasser ud fra DMR's SOAP-service vie værktøjet wsdl2php. Så vidt jeg husker måtte jeg rette den klasse jeg bruger lidt til før det virkede.

Dernæst har jeg hentet PHP-biblioteket wse-php som hjælper med at signerer SOAP-kaldet på den obskure måde som DMR syntes det skal laves ;-). Tror det var det der gjorde at jeg fik løst den fejl du sidder med.

I brug inkluderer jeg jeg wse-php samt de php-klasser jeg fik genereret vie wsdl2php:

require_once 'wse-php/soap-wsse.php';
require_once 'DMR/USSekundaereErhvervsmaessigeBrugere/USKoeretoejRegistreringSekundaerErhvervListeHent_I.php';
require_once 'DMR/USSekundaereErhvervsmaessigeBrugere/HovedOplysningerType.php';

Og for at gøre brug af det lavede jeg en klasse der nedarver soap-klienten og lader mig flette signeringen ind i requestet:

class DMRSoap extends SoapClient {

    public $privatekey = NULL;
    public $pkcs12_cert = array();
    public $key = NULL;

  public function __doRequest($request, $location, $saction, $version) {
    $doc = new DOMDocument('1.0');
    $doc->loadXML($request);

        $objWSSE = new WSSESoap($doc);
    $objWSSE->signAllHeaders = TRUE;

    $objWSSE->addTimestamp();

        $options = array("insertBefore" => FALSE);
    $objWSSE->signSoapDoc($this->key, $options);

    $token = $objWSSE->addBinaryToken($this->pkcs12_cert["cert"]);
    $objWSSE->attachTokentoSig($token);

    return parent::__doRequest($objWSSE->saveXML(), $location, $saction, $version);
  }

  public function setCompanyCertificate($certificateFile, $certificatePasswd) {
    if (trim($certificateFile)!="" || is_readable($certificateFile)) {
      if (openssl_pkcs12_read(file_get_contents($certificateFile), $this->pkcs12_cert, $certificatePasswd)) {
        if (openssl_pkey_export($this->pkcs12_cert["pkey"],$this->privatekey)) {
          $this->key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
          $this->key->loadKey($this->privatekey);
          return true;
        } else {
          error_log("Unable to export private key from certificatefile: ".$certificateFile);
        }
      } else {
        error_log("Unable to read from certificatefile: ".$certificateFile);
      }
    } else {
      error_log("Unable to locate certificatefile: ".$certificateFile);
    }
    $this->pkcs12_cert = array();
    $this->privatekey = NULL;
    $this->key = NULL;
    return false;
  }
}


Med denne klasse opretter jeg så SOAP-kaldet:

    $sc = new DMRSoap($this->wsdlUrl);
    if ($sc->setCompanyCertificate($this->certificateFile, $this->certificatePasswd)) {
      $dmrParam = new USKoeretoejRegistreringSekundaerErhvervListeHent_I();
      $dmrParam->RegistreringNummerNummer = $this->LicensePlateNumber;
      $dmrParam->HovedOplysninger = new HovedOplysningerType();
      $dmrParam->HovedOplysninger->TransaktionIdentifikator = string::createUuid();
      $dmrParam->HovedOplysninger->TransaktionTid = date("Y-m-d\TH:i:s\Z");
    } else {
      $this->isValid = false;
      $this->criticalError = true;
      dmr::dmrlog("Invalid certificate file \"".basename($this->certificateFile)."\" or wrong/empty certificate password");
      $this->lastErrorMsg = "Firma certifikat kunne ikke læses pga. ugyldig certifikatfil \"".basename($this->certificateFile)."\" eller forkert certifikat kodeord.";
      return false;
    }


og kalder så den funktion hos DMR som jeg har brug for for at få mine data ud:

      $out = $sc->__soapCall("getUSKoeretoejRegistreringSekundaerErhvervListeHent",
                array( new SoapParam($dmrParam, 'Request') ),
                array( 'uri' => 'http://skat.dk/dmr/2007/05/31/', 'soapaction' => '' )
              );




Mere kan jeg vist ikke tillade mig at komme med, så jeg håber det hjælper ;-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester