-
-
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 <[email protected]> | |
* @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); | |
} | |
} | |
?> |
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");
}
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
@ibuxeda , Could you solve the problem?
Hola, tengo el mismo problema, lo pudieron resolver? Saludos.
Hello, I have the same problem, could you fix it? Regards.
$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
Finally!!!! Something that works!! Thanks!!!