Ver Mensaje Individual
  #1 (permalink)  
Antiguo 26/10/2011, 08:58
jasv
 
Fecha de Ingreso: julio-2008
Ubicación: Caldas, Antioquia, Colombia
Mensajes: 81
Antigüedad: 16 años, 4 meses
Puntos: 4
XML Signature con PHP

Hola a todos,

Estoy haciendo un desarrollo donde necesito un consumir un servicio web que implementa WS-Security.

Para garantizar la característica de Non-Repudiation (es decir, que quien envíe un mensaje no puede negar que lo ha hecho), se deben firmar digitalmente los mensajes XML a ser enviados al servicio web usando WS-Security, específicamente XML Signature.

Una persona que ya hizo pruebas de conexión al WS (con java) me envió un archivo keyStore que utilizó y le funcionó. Yo con una herramienta llamada portecle, extraje la clave privada y el certificado, y estoy usando una librería que encontré llamada soap-wsse.php (esta usa otra librería llamada xmlseclibs). Con esto ya he podido firmar el mensaje, sin embargo obtengo el siguiente mensaje:


Código:
WSDoAllReceiver: security processing failed (actions number mismatch)

Éste es el código que estoy utilizando.

Código PHP:
<?php
require_once('soap-wsse2.php');

class 
WSSoapClient extends SoapClient 
{
    
//Ruta del fichero de la clave privada
    
public $key_file="";
    
//Passphrase de la clave privada
    
public $passphrase="";
    
//Ruta del fichero del certificado
    
public $cert_file="";
    
//Mensaje SOAP enviado
    
public $soap_sent="";
    
    public 
$user "";
    
    public 
$password "";
    
    function 
__doRequest($request$location$saction$version)
    {
        
//return parent::__doRequest($request, $location, $action, $version);
        //Creamos un DOMDocument
        
$doc = new DOMDocument('1.0');
        
//Cargamos el XML pasado por parámetro
        
$doc->loadXML($request);
        
//Creamos una instancia de WSSESoap con el documento, sin "mustUnderstand" ni "actor"
        
$objWSSE = new WSSESoap($doc,false,false);
        
        
$objWSSE->addTimestamp(300); 
        
        
$objWSSE->addUserToken($this->user$this->password);
        
        
//Creamos una instacian de XMLSecurityKey con el RSA SHA1 y de tipo privado
        
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1,array ('type'=>'private'));
        
//Pasamos el valor de passphrase
        
$objKey->passphrase=$this->passphrase;
        
//Cargamos la clave privada con la ruta del fichero, que es fichero y que no es certificado
        
$objKey->loadKey($this->key_fileTRUE);
        
//Firmamos el mensaje
        
$objWSSE->signSoapDoc($objKey);
        
//Añadimos el BinarySecurityToken, pasamos el contenido del certificado, le decimos que es formato PEM
        
$token $objWSSE->addBinaryToken(file_get_contents($this->cert_file),TRUE);
        
//Añadimos el KeyInfo
        
$objWSSE->attachTokentoSig($token);

        
//Guardamos el XML enviado
        
$this->soap_sent=$objWSSE->saveXML();
        echo 
htmlentities($this->soap_sent);
        
//Llamamos al método __doRequest padre
        
return parent::__doRequest($this->soap_sent$location$saction$version);
    }
}

$auth_login 'YYYYYYYY';
$auth_password 'ZZZZZZ';

$opciones = array(
    
'proxy_host' => 'proxy',
    
'proxy_port' => '8080',
    
'proxy_login' => 'user',
    
'proxy_password' => 'xxxxxxxxxx',
    
'trace' => 1,
    
'cache_wsdl' => WSDL_CACHE_NONE,
    
'login' => $auth_login,
    
'password' => $auth_password
);

$url 'http://.../ConfrontaWebService?wsdl';

$pk_file 'keys/test_pk.pem';
$cert_file 'keys/test_cert.cer';
$pk_passphrase 'XXXXXXXXX';

$objParametrosDTO = new stdClass();
$objParametrosDTO->secuenciaCuestionario '10';
$objParametrosDTO->secuenciaEmpleado '12';
$objParametrosDTO->tipoIdentificacion '1';
$objParametrosDTO->numeroIdentificacion '12312';
$objParametrosDTO->telefono '1231';
$objParametrosDTO->departamento '1';
$objParametrosDTO->ciudad '1';
$objParametrosDTO->tipoEntidad '1';
$objParametrosDTO->codigoEntidad '1';
$objParametrosDTO->clave $auth_login;
$objParametrosDTO->password $auth_password;

$objParametrosConsulta = new stdClass();
$objParametrosConsulta->codigoInformacion '';
$objParametrosConsulta->motivoConsulta '';
$objParametrosConsulta->numeroIdentificacion '';
$objParametrosConsulta->tipoIdentificacion '';

try{
    
$sClient = new WSSoapClient($url$opciones);
    
//Cargamos la clave, passphrase y certificado
    
$sClient->key_file=$pk_file;
    
$sClient->cert_file=$cert_file;
    
$sClient->passphrase=$pk_passphrase;
    
$sClient->user $auth_login;
    
$sClient->password $auth_password;
    
    
//$result = $sClient->consultaPlano($objParametrosConsulta);
    
$result $sClient->obtenerCuestionario($objParametrosDTO);
    
var_dump($result);
}catch(
Exception $e){
    echo 
"<h2>Exception Error!</h2>"
    echo 
$e->getMessage(); 
    
//echo "<h2>Last Request!</h2>"; 
    //echo htmlentities($sClient->__getLastRequest());
}

?>
Agradezco cualquier ayuda que me puedan brindar,

Gracias de antemano.

Saludos.

Info adicional

Utilizando un programa llamado SoapUI, envié el XML que genera mi código, la respuesta del servidor fue distinta:

Código:
WSDoAllReceiver: security processing failed; nested exception is: 
org.apache.ws.security.WSSecurityException: The signature verification failed
Extraña cosa, cuando el mensaje es exactamente el mismo el mensaje es distinto. Espero que ésto sirva de algo.

Última edición por jasv; 26/10/2011 a las 09:57 Razón: Info adicional