събота, май 30, 2009

PHP, Web services and authentication header

Problem: Use Web Service which requires authentication header with PHP 5+ and SoapClient object.

Soap Xml request:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SOAP-ENV:Header>
    <m:SOAPAuthenticationHeader xmlns:m="http://www.mydomain.com">
      <m:username>myusername</m:username>
      <m:password>mypassword</m:password>
    </m:SOAPAuthenticationHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <m:WebServiceMethodName xmlns:m="http://www.mydomain.com">
      <m:param1>some value</m:param1>
      <m:param2>some value</m:param2>
      <m:param3>some value</m:param3>
    </m:WebServiceMethodName>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


In case you have to use authentication headers when calling a Web Service, you cannot use the intuitive way like below, because all of these go inside the body part of the envelope (SOAP-ENV Body):


$params = new StdClass();
$params->Header->username = "myusername";
$params->Header->password = "mypassword";

$params->Body->param1 = "some value";
$params->Body->param2 = "some value";
$params->Body->param3 = "some value";


The above object does not transform into SOAP request with header envelope part and body envelope part - it is simply transformed as body envelope part with child elements header and body. So, access to the Web Service is forbidden as there is no authentication header envelope.

Solution: Create separate object for authentication header envelope and separate object for body envelope.


define(WSDL_URL, "http://www.mydomain.com/webservicepath?wsdl");

# create authentication headers (SOAP Header envelope)
$params_header = new stdClass();
$params_header->username = "myusername";
$params_header->password = "mypassword";

# create request parameters (SOAP Body envelope)
$params = new stdClass();
$params->param1 = "some value";
$params->param2 = "some value";
$params->param3 = "some value";

# create soap client object
$soap_client = new SoapClient(WSDL_URL, array("connection_timeout"=>5, 'trace'=>1));

# create soap header object
$soap_header = new SoapHeader("http://www.mydomain.com", "SOAPAuthenticationHeader", $params_header);

$soap_client->__setSoapHeaders(array($soap_header));

try
{
  # call the method of the service
  $result = $soap_client->WebServiceMethodName(params);
}
catch(SoapFault $exception)
{
  echo $exception;
}

Няма коментари: