[php][soap] geldige soap request maken

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • eXcyle
  • Registratie: Juni 2002
  • Laatst online: 30-08 23:45
Ik ben al enige tijd bezig met het opzetten van een geldige soap request naar onze elo (it's Learning) maar krijg dit met PHP niet echt voor elkaar.

Ik ben begonnen met het testen in SoapUI om in elk geval makkelijk de juiste request body te maken, en dit is mij dus ook wel gelukt. Ik krijg het nu alleen niet voor elkaar deze zelfde request in PHP in elkaar te zetten.

De soap server gebruikt een wsse beveiliging (username etc in de header dus) en ik zal dus zowel de headers als de body zelf moeten genereren.

als ik via SoapUI kijk naar een valide request ziet deze er als volgt uit :
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
POST /WCFServiceLibrary/ImsEnterpriseServicesPort.svc HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://www.imsglobal.org/soap/pms/readPerson"
Content-Length: 1344
Host: soapserver
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

<soapenv:Envelope xmlns:ims="http://www.imsglobal.org/services/common/imsMessBindSchema_v1p0" xmlns:ims1="http://www.imsglobal.org/services/pms/xsd/imsPersonManMessSchema_v1p0" xmlns:ims2="http://www.imsglobal.org/services/common/imsCommonSchema_v1p0" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
        <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="UsernameToken-2">
                <wsse:Username>username</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">BzyMqoa26ro/avnxOlngCw==</wsse:Nonce>
                <wsu:Created>2012-09-23T08:55:09.351Z</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
        <ims:syncRequestHeaderInfo>
            <ims:messageIdentifier>1</ims:messageIdentifier>
        </ims:syncRequestHeaderInfo>"
    </soapenv:Header>
    <soapenv:Body>
        <ims1:readPersonRequest>
            <ims1:sourcedId>
                <ims2:identifier>1234joe</ims2:identifier>
            </ims1:sourcedId>
        </ims1:readPersonRequest>
    </soapenv:Body>
</soapenv:Envelope>


Vrij duidelijk, echter als ik deze in PHP nabouw (ik heb het eerst in native PHP Soap geprobeerd, en ben hierna naar nuSoap over gesprongen) kom ik op de volgende code uit :
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
error_reporting(E_ALL);
ini_set('display_errors','On');

require_once('./lib/nusoap.php');

$username = "username";
$password = "password";
$endpoint = "https://soapserver/WCFServiceLibrary/ImsEnterpriseServicesPort.svc";
$soapaction = "http://www.imsglobal.org/soap/pms/readPerson";

$client = new nusoap_client($endpoint, false);
$client->soap_defencoding = 'UTF-8';

$nonce = md5(rand());
$created = date("Y-m-d H:i:s");
$headers = '
<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="UsernameToken">
        <wsse:Username>'.$username.'</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">'.$password.'</wsse:Password>
        <wsse:Nonce>'.$nonce.'</wsse:Nonce>
        <wsu:Created>'.$created.'</wsu:Created>
    </wsse:UsernameToken>
</wsse:Security>
<ims:syncRequestHeaderInfo>
    <ims:messageIdentifier>1</ims:messageIdentifier>
</ims:syncRequestHeaderInfo>
';

$body = '
<ims1:readPersonRequest>
    <ims1:sourcedId>
        <ims2:identifier>1234joe</ims2:identifier>
    </ims1:sourcedId>
</ims1:readPersonRequest>
';

$msg = $client->serializeEnvelope($body, $headers);
$result = $client->send($msg, $soapaction);

// voor debugging
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';

?>


Dit genereert de volgende soap request:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
POST /WCFServiceLibrary/ImsEnterpriseServicesPort.svc HTTP/1.0
Host: soapserver
User-Agent: NuSOAP/0.9.5 (1.123)
Content-Type: text/xml; charset=UTF-8
SOAPAction: "http://www.imsglobal.org/soap/pms/readPerson"
Content-Length: 1313

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Header>
        <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="UsernameToken">
                <wsse:Username>username</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
                <wsse:Nonce>6e875a13a2d9ede1aefbc93d057b84e5</wsse:Nonce>
                <wsu:Created>2012-09-23 11:00:33</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
        <ims:syncRequestHeaderInfo>
            <ims:messageIdentifier>1</ims:messageIdentifier>
        </ims:syncRequestHeaderInfo>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ims1:readPersonRequest>
            <ims1:sourcedId>
                <ims2:identifier>1234joe</ims2:identifier>
            </ims1:sourcedId>
        </ims1:readPersonRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

wat kleine verschillen, maar voor zover ik kan beoordelen geen dealbreakers.... zou je denken.... ik krijg namelijk als antwoord het volgende terug :
code:
1
2
3
4
5
6
7
8
9
10
HTTP/1.1 100 Continue

HTTP/1.1 400 Bad Request
Cache-Control: private
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
ITSL: ITSL529
Date: Sun, 23 Sep 2012 09:00:33 GMT
Content-Length: 0


Wie o wie kan mij hierbij in de goede richting schoppen, want ik kom er even niet meer uit :'( :'(

Acties:
  • 0 Henk 'm!

  • Kalentum
  • Registratie: Juni 2004
  • Nu online
Geen idee, maar heel even Googlen leert dat er mensen zijn die de native php soap client gebruiken in combinatie met WSSE. Misschien kun je daar eerst naar kijken? Het lijkt me niet zo'n goed idee om zelf XML te gaan bakken.

Acties:
  • 0 Henk 'm!

  • eXcyle
  • Registratie: Juni 2002
  • Laatst online: 30-08 23:45
Uiteraard ben ik ook begonnen zonder het zelf brouwen van de xml, maar dit gaat ook niet goed. en ik lees ook overal dat native php soap en wsse een rampzalige combo is...

Ik ben nu wel iets verder, ik heb nu de volgende code :
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
error_reporting(E_ALL);
ini_set('display_errors','On');

$url = 'https://soapserver/WCFServiceLibrary/ImsEnterpriseServicesPort.svc?wsdl';
$username = 'username';
$password = 'password';

$soapclient = new SoapClient($url, array('trace'=>1));

$authheaderdata = '
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:UsernameToken>
            <wsse:Username>'.$username.'</wsse:Username>
            <wsse:Password>'.$password.'</wsse:Password>
         </wsse:UsernameToken>
    </wsse:Security>
';
$authvars = new SoapVar($authheaderdata,XSD_ANYXML);
$syncheader=new SoapHeader("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security",$authvars);
$soapclient->__setSoapHeaders($syncheader);

$parameters['sourcedId']['identifier'] = "1234joe";

$soapclient->__soapCall('ReadPerson',array($parameters));
var_dump($soapclient->__getLastRequest());
var_dump($soapclient->__getLastResponse());

?>


dit genereert de volgende request :
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.imsglobal.org/services/common/imsCommonSchema_v1p0" xmlns:ns2="http://www.imsglobal.org/services/pms/xsd/imsPersonManMessSchema_v1p0" xmlns:ns3="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <SOAP-ENV:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
             <wsse:UsernameToken>
                <wsse:Username>username</wsse:Username>
                <wsse:Password>password</wsse:Password>
             </wsse:UsernameToken>
        </wsse:Security>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns2:readPersonRequest>
            <ns2:sourcedId>
                <ns1:identifier>1234joe</ns1:identifier>
            </ns2:sourcedId>
        </ns2:readPersonRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


met als antwoord :
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <s:Header>
    <h:syncResponseHeaderInfo xmlns:h="http://www.imsglobal.org/services/common/imsMessBindSchema_v1p0" xmlns="http://www.imsglobal.org/services/common/imsMessBindSchema_v1p0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <messageIdentifier/>
        <statusInfo>
            <codeMajor>failure</codeMajor>
            <severity>error</severity>
            <codeMinor>
                <codeMinorField>
                    <codeMinorName>personmanagement</codeMinorName>
                    <codeMinorValue>invalidrequest</codeMinorValue>
                </codeMinorField>
            </codeMinor>
            <messageIdRef/>
            <description>
                <language xmlns="http://www.imsglobal.org/services/common/imsCommonSchema_v1p0">en-US</language>
                <text xmlns="http://www.imsglobal.org/services/common/imsCommonSchema_v1p0">Part or all the supplied data was detected as invalid by ES standart</text>
            </description>
        </statusInfo>
        </h:syncResponseHeaderInfo>
        <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <u:Timestamp u:Id="_0">
                <u:Created>2012-09-23T12:26:06.936Z</u:Created>
                <u:Expires>2012-09-23T12:31:06.936Z</u:Expires>
            </u:Timestamp>
        </o:Security>
    </s:Header>
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <readPersonResponse xmlns="http://www.imsglobal.org/services/pms/xsd/imsPersonManMessSchema_v1p0"/>
    </s:Body>
</s:Envelope>


hieruit maak ik op dat in elk geval authenticatie via de wsse header goed gaat, haal ik namelijk deze header weg dan krijg ik namelijk het volgende terug :
XML:
1
2
3
4
5
6
7
8
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <s:Fault>
            <faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
            <faultstring xml:lang="nb-NO">An error occurred when verifying security for the message.</faultstring>
        </s:Fault>
    </s:Body>
</s:Envelope>

En verander ik UsernameToken in UsernameTokenFout krijg ik meteen een "Bad Request" terug. Wat volgens mij betkend dat de wsse dus inderdaad goed gaat.

De melding die ik krijg kan ik in SoapUI op de volgende manier reproduceren;
het volgende uit de header halen
XML:
1
2
3
    <ims:syncRequestHeaderInfo>
        <ims:messageIdentifier>1</ims:messageIdentifier>
    </ims:syncRequestHeaderInfo>


als ik dit toevoeg :
PHP:
1
2
3
4
5
6
7
8
9
10
11
<?php
$syncheaderdata = '
    <ims:syncRequestHeaderInfo xmlns:ims="http://www.imsglobal.org/services/common/imsMessBindSchema_v1p0">
        <ims:messageIdentifier>1</ims:messageIdentifier>
    </ims:syncRequestHeaderInfo>
';
$syncvars = new SoapVar($syncheaderdata,XSD_ANYXML);
$syncheader=new SoapHeader("http://www.imsglobal.org/services/common/imsMessBindSchema_v1p0", "syncRequestHeaderInfo",$syncvars);

$soapclient->__setSoapHeaders(array($authheader,$syncheader));
?>

lijkt alles nu te werken :o :*) 8) :D _/-\o_