<?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, WSS4J servers and CXF. | |
* | |
* @author Roger Veciana - http://www.phpclasses.org/browse/author/233806.html | |
* @author John Kary <johnkary@gmail.com> | |
* @author Alberto Martínez - https://gist.github.com/Turin86/5569152 | |
* @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); | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
This saved me too! Thanks! |
This comment has been minimized.
This comment has been minimized.
Thank you! This has absolutely saved my hours of work with another framework that was truly outdated. Cheers! |
This comment has been minimized.
This comment has been minimized.
excuse me but for mutual authentication with digital signatures as you can do? |
This comment has been minimized.
This comment has been minimized.
Thanks a lot! |
This comment has been minimized.
This comment has been minimized.
The nonce is represent by base64, but I don't see any decode ? You use it from $nonce. I expected something like this: base64($nonce). Does it work ? |
This comment has been minimized.
This comment has been minimized.
Thanks very much |
This comment has been minimized.
This comment has been minimized.
Thanks a lot. I don't know why some people keeps using this outdated and inconvenient standard. They should move to RESTful Webservices >.< |
This comment has been minimized.
This comment has been minimized.
Nice, but how do i use this class? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
hi, how should i pass username and password |
This comment has been minimized.
This comment has been minimized.
how to implement? Please share sample code? |
This comment has been minimized.
This comment has been minimized.
How to see last request? I have put |
This comment has been minimized.
This comment has been minimized.
Yes, you would like to sign with an ssl certificate, how would the process be |
This comment has been minimized.
This comment has been minimized.
Call the WSSoapClient contructor (does not override the SoapClient constructor) with the appropiate parameters. |
This comment has been minimized.
This comment has been minimized.
You will have an example of consumption and use this in the header that I get from the SOAPUI `soapenv:Header </soapenv:Header>` |
This comment has been minimized.
This comment has been minimized.
you got an example with the certificate too? |
This comment has been minimized.
This comment has been minimized.
Hi anyone knows how to implement ws security with a certificate X509 to a soap request instead? need help . thanks |
This comment has been minimized.
Man this saved the day, I tried the original and it wasn't working for my needs but your fork saved me. Thanks.