Skip to content

Instantly share code, notes, and snippets.

@tschoffelen
Forked from Turin86/WSSoapClient.php
Created August 12, 2013 14:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tschoffelen/6211278 to your computer and use it in GitHub Desktop.
Save tschoffelen/6211278 to your computer and use it in GitHub Desktop.
<?php
/**
* This class can add WSSecurity authentication support to SOAP clients
* implemented with the PHP 5 SOAP extension.
*
* It extends the PHP 5 SOAP client support to add the necessary XML tags to
* the SOAP client requests in order to authenticate on behalf of a given
* user with a given password.
*
* This class was tested with Axis and WSS4J servers.
*
* @author Roger Veciana - http://www.phpclasses.org/browse/author/233806.html
* @author John Kary <johnkary@gmail.com>
* @author Alberto Martínez - https://github.com/Turin86
* @see http://stackoverflow.com/questions/2987907/how-to-implement-ws-security-1-1-in-php5
*/
class WSSoapClient extends SoapClient
{
private $OASIS = 'http://docs.oasis-open.org/wss/2004/01';
/**
* WS-Security Username
* @var string
*/
private $username;
/**
* WS-Security Password
* @var string
*/
private $password;
/**
* WS-Security PasswordType
* @var string
*/
private $passwordType;
/**
* Set WS-Security credentials
*
* @param string $username
* @param string $password
* @param string $passwordType
*/
public function __setUsernameToken($username, $password, $passwordType)
{
$this->username = $username;
$this->password = $password;
$this->passwordType = $passwordType;
}
/**
* Overwrites the original method adding the security header.
* As you can see, if you want to add more headers, the method needs to be modified.
*/
public function __call($function_name, $arguments)
{
$this->__setSoapHeaders($this->generateWSSecurityHeader());
return parent::__call($function_name, $arguments);
}
/**
* Generate password digest.
*
* Using the password directly may work also, but it's not secure to transmit it without encryption.
* And anyway, at least with axis+wss4j, the nonce and timestamp are mandatory anyway.
*
* @return string base64 encoded password digest
*/
private function generatePasswordDigest()
{
$this->nonce = mt_rand();
$this->timestamp = gmdate('Y-m-d\TH:i:s\Z');
$packedNonce = pack('H*', $this->nonce);
$packedTimestamp = pack('a*', $this->timestamp);
$packedPassword = pack('a*', $this->password);
$hash = sha1($packedNonce . $packedTimestamp . $packedPassword);
$packedHash = pack('H*', $hash);
return base64_encode($packedHash);
}
/**
* Generates WS-Security headers
*
* @return SoapHeader
*/
private function generateWSSecurityHeader()
{
if ($this->passwordType === 'PasswordDigest')
{
$password = $this->generatePasswordDigest();
$nonce = sha1($this->nonce);
}
elseif ($this->passwordType === 'PasswordText')
{
$password = $this->password;
$nonce = sha1(mt_rand());
}
else
{
return '';
}
$xml = '
<wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="' . $this->OASIS . '/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>' . $this->username . '</wsse:Username>
<wsse:Password Type="' . $this->OASIS . '/oasis-200401-wss-username-token-profile-1.0#' . $this->passwordType . '">' . $password . '</wsse:Password>
<wsse:Nonce EncodingType="' . $this->OASIS . '/oasis-200401-wss-soap-message-security-1.0#Base64Binary">' . $nonce . '</wsse:Nonce>';
if ($this->passwordType === 'PasswordDigest')
{
$xml .= "\n\t" . '<wsu:Created xmlns:wsu="' . $this->OASIS . '/oasis-200401-wss-wssecurity-utility-1.0.xsd">' . $this->timestamp . '</wsu:Created>';
}
$xml .= '
</wsse:UsernameToken>
</wsse:Security>';
return new SoapHeader(
$this->OASIS . '/oasis-200401-wss-wssecurity-secext-1.0.xsd',
'Security',
new SoapVar($xml, XSD_ANYXML),
true);
}
}
?>
@AntonioCS
Copy link

Finally!!!! Something that works!! Thanks!!!

@Jonijo
Copy link

Jonijo commented May 13, 2016

In case youre wondering how to implement.

$stub = new WSSoapClient('https://my-wsdl-location?wsdl', array(
'trace' => 1,
'encoding' => 'UTF-8',
));

$functions = $stub->__getFunctions();
var_dump($functions);

$stub->__setUsernameToken('username', 'password', 'PasswordText');

try {

    $config= array("Value"=>"somedata");

    $var = $stub->queryValue($config);

    var_dump($var);


} catch(SoapFault $fault) {
    print("Fault string: " . $fault . "\n");
}

@ibuxeda
Copy link

ibuxeda commented Oct 23, 2017

Hi, this code is very usefull, but, I'm having some troubles to make him work in my project, my scenario is the next one, I need to consume a web service from an financial entity with a lot of security parameters. I test the web service with SOAPUI app an its working fine. The security is at IP level (IP fixed), SOAP header with ws-security (like this code) and they give me an certificate to installl on the server computer. I was testing the code with others web services and its working fine. When i try to connect to web service i have the next error message:

Fault string: SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://linkpagosservices.redlink.com.ar/linkpagosservices/AltaDeudasServices?wsdl' : failed to load external entity "https://linkpagosservices.redlink.com.ar/linkpagosservices/AltaDeudasServices?wsdl" in C:\inetpub\wwwroot\wsLinkPHP\index.php:39 Stack trace: #0 C:\inetpub\wwwroot\wsLinkPHP\index.php(39): SoapClient->SoapClient('https://linkpag...', Array) #1 {main}

The code i'm using

'; $options = array( 'soap_version'=>SOAP_1_1, 'cache_wsdl'=>WSDL_CACHE_NONE, 'connection_timeout'=>15, 'trace'=>1, 'encoding'=>'UTF-8', 'exceptions'=>true, 'keep_alive' => true, 'location' => 'https://linkpagosservices.redlink.com.ar:443/linkpagosservices/AltaDeudasServices'); //endpoint taked from SOAPUI try { echo '
object
'; //$webservice = new WSSoapClient('https://linkpagosservices.redlink.com.ar/linkpagosservices/AltaDeudasServices?wsdl', array('trace' => 1, 'encoding' => 'UTF-8',)); $webservice = new WSSoapClient('https://linkpagosservices.redlink.com.ar/linkpagosservices/AltaDeudasServices?wsdl', $options); echo '
HEADER
'; $webservice->__setUsernameToken('USER', 'PASS', 'PasswordText'); // echo '
object created
'; $functions = $webservice->__getFunctions(); echo '
DUMP
'; var_dump($functions); echo 'The end'; } catch(SoapFault $fault) { print("Fault string: " . $fault . "\n"); } ?>

If anyone can help me please, I'll be very greatful.

Regards

@pablopassoni
Copy link

@ibuxeda , Could you solve the problem?

@alanviera
Copy link

Hola, tengo el mismo problema, lo pudieron resolver? Saludos.

Hello, I have the same problem, could you fix it? Regards.

@jgarciafinanciat
Copy link

$stub = new WSSoapClient('https://my-wsdl-location?wsdl', array(
'trace' => 1,
'encoding' => 'UTF-8',
));

$functions = $stub->__getFunctions();
var_dump($functions);

$stub->__setUsernameToken('username', 'password', 'PasswordText');

try {

$config= array("Value"=>"somedata");

$var = $stub->queryValue($config);

var_dump($var);

} catch(SoapFault $fault) {
print("Fault string: " . $fault . "\n");
}

thank you very much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment