Laurent31 Laurent31 - 1 month ago 13
PHP Question

How to do authentication using SOAP Header and PHP?

I look for an example of Web service's creation using an authentification SOAP header and PHP.
I found an acticle on http: // stackoverflow.com with a code given by EricP in an answer to a question below:

How to do authentication using SOAP?

I don't know why it does not work. It seems to me that the program does not pass in the function APIValidate which is supposed to verify the authenticity of the APIKey.
What is what you would know why it does not work?

I found other examples of code using the same principle and I always block in the same place.
I use in localhost Wamp and PHP version 5.2.3.
Does it exist a particular module to be activated in wamp or Apache or PHP?

Thank you in advance for your answers.

Here is my code:

file portfolio-lookup-server.php

<?php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache

class PortfolioLookupService {

private $apiKey = '123456';

private $portfolios = array(
'WPOW' => 'Power 96 party station.',
'WQAM' => 'Sports radio site.',
'WJBR' => 'Cool sites for bands.',
'WKIS' => 'Kiss Country 2',

);

public function APIValidate($auth){

return "------>>>auth=".$auth->apiKey.'<br />'."apikey".$this->apiKey."<br />";
if($auth->apiKey != $this->apiKey){
throw new SoapFault("Server", "Incorrect key");

}


}

function getPortfolioByName($portfolioName) {
//print_r($portfolioName); exit();
if (isset($this->portfolios[$portfolioName])) {
return $this->portfolios[$portfolioName];
} else {
return 'Portfolio name "'.$portfolioName.'" not found.';
//throw new SoapFault('code', 'string', 'actor', 'detail', 'name', 'header');
throw new SoapFault("Server","Unknown Name '$portfolioName'.");
}
}

function getPortfoliosAll() {
return $this->portfolios;
}

}

$server = new SoapServer("portfolio-lookup.wsdl");
$server->setClass("PortfolioLookupService");
$server->handle();
?>


file portfolio-lookup-client.php

<?php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
class portfolioLookupAuth
{
public $apiKey;
public function __construct($key)
{
$this->apiKey = $key;
}
}
//$apiKey = "123456";
$apiKey = "125456";
$url = 'http://localhost/WebservicePortfolio/portfolio-lookup.wsdl';

$client = new SoapClient($url, array("trace" => 1, "exception" => 0));

// Create the header
$auth = new portfolioLookupAuth($apiKey);
// SoapHeader::__construct ( string $namespace , string $name [, mixed $data [, bool $mustunderstand [, string $actor ]]] )
$header = new SoapHeader($url, "APIValidate", $auth, false);

try {

$result = $client->__soapCall("getPortfolioByName", array("portfolioName" => "WQAM"), NULL, $header);

print_r($result);

print "<pre>\n"; print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
print "Response:\n".htmlspecialchars($client->__getLastResponse())."\n"; print "</pre>";
print_r($auth);
print_r($header);

} catch (SoapFault $exception) {

echo 'Exception Thrown: '.$exception->faultstring.'<br><br>';

}

?>


file portfolio-lookup.wsdl

<?xml version ='1.0' encoding ='UTF-8' ?>

<definitions name='PortfolioLookup'

targetNamespace='http://localhost/WebservicePortfolio'

xmlns:tns='PortfolioLookup'

xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'

xmlns:xsd='http://www.w3.org/2001/XMLSchema'

xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'

xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'

xmlns='http://schemas.xmlsoap.org/wsdl/'>

<message name='getPortfolioByNameRequest'>
<part name='portfolioName' type='xsd:string'/>
</message>
<message name='getPortfolioByNameResponse'>
<part name='Result' type='xsd:string'/>
</message>


<message name='getPortfoliosAllRequest'>
<part name='portfolioName' type='xsd:string'/>
</message>
<message name='getPortfoliosAllResponse'>
<part name='Result' type='xsd:array'/>
</message>


<message name='APIValidateRequest'>
<part name='apiKey' type='xsd:string'/>
</message>
<message name='APIValidateResponse'>
<part name='testReturn' type='xsd:string'/>
</message>



<portType name='PortfolioLookupPortType'>

<operation name='getPortfolioByName'>
<input message='tns:getPortfolioByNameRequest'/>
<output message='tns:getPortfolioByNameResponse'/>
</operation>

<operation name='getPortfoliosAll'>
<input message='tns:getPortfoliosAllRequest'/>
<output message='tns:getPortfoliosAllResponse'/>
</operation>

<operation name='APIValidate'>
<input message='tns:APIValidateRequest'/>
<output message='tns:APIValidateResponse'/>
</operation>

</portType>

<binding name='PortfolioLookupBinding' type='tns:PortfolioLookupPortType'>

<soap:binding style='rpc'
transport='http://schemas.xmlsoap.org/soap/http'/>


<operation name='getPortfolioByName'>
<soap:operation soapAction='urn:PortfolioLookup#getPortfolioByName'/>
<input>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>


<operation name='getPortfoliosAll'>
<soap:operation soapAction='urn:PortfolioLookup#getPortfoliosAll'/>
<input>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:PortfolioLookup'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>




</binding>

<service name='PortfolioLookupService'>

<port name='PortfolioLookupPort' binding='PortfolioLookupBinding'
<soap:address location='http://localhost/WebservicePortfolioportfolio-lookup-server.php'/>
</port>

</service>

</definitions>

Answer

I found the solution.

You should declare the function APIValidate in the binding in the file wsdl.

<operation name='APIValidate'>
    <soap:operation soapAction='urn:PortfolioLookup#APIValidate'/>
    <input>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </input>
    <output>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </output>
  </operation>  

And you should d├ęclare in type array the input request in part message.

<message name='APIValidateRequest'>
<part name='apiKey' type='xsd:array'/>
</message>

Above the code final:

file portfolio-lookup.wsdl

<?xml version ='1.0' encoding ='UTF-8' ?>

<definitions name='PortfolioLookup'

  targetNamespace='http://localhost/WebservicePortfolio'

  xmlns:tns='PortfolioLookup'

  xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'

  xmlns:xsd='http://www.w3.org/2001/XMLSchema'

  xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'

  xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'

  xmlns='http://schemas.xmlsoap.org/wsdl/'>

<message name='getPortfolioByNameRequest'>
  <part name='portfolioName' type='xsd:string'/>
</message>
<message name='getPortfolioByNameResponse'>
  <part name='Result' type='xsd:string'/>
</message>


<message name='getPortfoliosAllRequest'>
  <part name='portfolioName' type='xsd:string'/>
</message>
<message name='getPortfoliosAllResponse'>
  <part name='Result' type='xsd:array'/>
</message>


<message name='APIValidateRequest'>
<part name='apiKey' type='xsd:array'/>
</message>
<message name='APIValidateResponse'>
<part name='testReturn' type='xsd:string'/>
</message>



<portType name='PortfolioLookupPortType'>

  <operation name='getPortfolioByName'>
    <input message='tns:getPortfolioByNameRequest'/>
    <output message='tns:getPortfolioByNameResponse'/>
  </operation>

  <operation name='getPortfoliosAll'>
    <input message='tns:getPortfoliosAllRequest'/>
    <output message='tns:getPortfoliosAllResponse'/>
  </operation>

    <operation name='APIValidate'>
    <input message='tns:APIValidateRequest'/>
    <output message='tns:APIValidateResponse'/>
    </operation>

</portType>

<binding name='PortfolioLookupBinding' type='tns:PortfolioLookupPortType'>

  <soap:binding style='rpc'
    transport='http://schemas.xmlsoap.org/soap/http'/>


  <operation name='getPortfolioByName'>
    <soap:operation soapAction='urn:PortfolioLookup#getPortfolioByName'/>
    <input>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </input>
    <output>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </output>
  </operation>


  <operation name='getPortfoliosAll'>
    <soap:operation soapAction='urn:PortfolioLookup#getPortfoliosAll'/>
    <input>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </input>
    <output>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </output>
  </operation>  


 <operation name='APIValidate'>
    <soap:operation soapAction='urn:PortfolioLookup#APIValidate'/>
    <input>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </input>
    <output>
      <soap:body use='encoded' namespace='urn:PortfolioLookup'
        encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
    </output>
  </operation>  

</binding>

<service name='PortfolioLookupService'>

  <port name='PortfolioLookupPort' binding='PortfolioLookupBinding'>
    <soap:address location='http://localhost/WebservicePortfolio/portfolio-lookup-server.php'/>
  </port>

</service>

</definitions>

file portfolio-lookup-client.php

<?php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
class portfolioLookupAuth 
{ 
    public $apiKey; 
    public function __construct($key) 
    { 
        $this->apiKey = $key; 
    } 
} 
$apiKey = "123456"; 

$url = 'http://localhost/WebservicePortfolio/portfolio-lookup.wsdl';

$client = new SoapClient($url, array("trace" => 1, "exception" => 0)); 

// Create the header 
$auth[]  = new portfolioLookupAuth($apiKey); 

// SoapHeader::__construct ( string $namespace , string $name [, mixed $data [, bool $mustunderstand [, string $actor ]]] ) 
$header = new SoapHeader($url, "APIValidate", $auth, false);   

  try {

  $result = $client->__soapCall("getPortfolioByName", array("portfolioName" => "WQAM"), NULL, $header);    

    print_r($result);

    print "<pre>\n"; print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
    print "Response:\n".htmlspecialchars($client->__getLastResponse())."\n"; print "</pre>";   
     echo "<br />================================auth====================<br />";
    print_r($auth);
    echo "<br />================================header====================<br />";
    print_r($header);
     print "<br />-------------->>>Request last header:\n".htmlspecialchars($client->__getLastRequestHeaders())."\n";

  } catch (SoapFault $exception) {

    echo 'Exception Thrown: '.$exception->faultstring.'<br><br>';  

  }

?>