我尝试使用usernameToken调用合作伙伴WS。我使用php5.2.x下的ws02 wsf_2.0.0,它很震撼。现在,我们希望在基于php5.3的不同解决方案上进行迁移,幸运的是,ws02提供了与php5.3兼容的2.1.0标记。我花时间阅读了这个新版本的新功能和文档,尤其是关于usernameToken的。我理解这个版本通过证书和私钥对usernameToken进行签名。我猜是AsymetricTransportBinding策略的b/c。就我而言,我不想通过证书或其他方式签署任何东西。我还读到ws02在一个单独的xml文件中提供了一种回退,以避免任何签名。
在阅读了许多帖子、论坛后,我需要社区的一些帮助,我完全陷入了困境。
以下是用于在php5.3-wsf2.1.0中请求WS的代码(使用HTTP)
$policy = new WSPolicy( $policy ); ( $policy is the one from the call_back folder with a file_get_contents() )
$security = new WSSecurityToken( array(
'user' => 'my_username',
'password' => 'my_password',
'passwordType' => 'Digest',
'ttl' => '300'
));
$this->oSoapClient = new WSClient( array(
wsdl: http://www.xxx.xx/comparatorservices/CalculationService?WSDL
to: http://www.xxx.xx/comparatorservices/CalculationService
useWSA: true
useSOAP: 1.1,
policy: $policy,
securityToken: $security
));
$proxy = $this->oSoapClient->getProxy();
$response = $proxy->wykonajKalkulacje( $MySuperRequestObject );
在此步骤:
- 我激活了调试跟踪(日志级别4)
我确认我的"to"是根据wsdl定义使用http
wsdl:port name="CalculationServiceHttpPort"binding="tns:CalculationServiceHTTP绑定"wsdlsoap:address location="http://www.xxxx.xx/comparatorservices/CalculationService"/wsdl:端口
现在,从调试日志中,我发现:
[Wed Jul 25 05:22:53 2012] [error] rampart_in_handler.c(91) [rampart]SOAP header cannot be found.
[Wed Jul 25 05:22:53 2012] [error] phase.c(224) Handler RampartInHandler invoke failed within phase Security
[Wed Jul 25 05:22:53 2012] [error] engine.c(657) Invoking phase Security failed
[Wed Jul 25 05:22:53 2012] [error] engine.c(262) Invoking operation specific phases failed for operation __OPERATION_OUT_IN__
[Wed Jul 25 05:22:53 2012] [error] /home/agruet/08_KRK_sources/wso2-wsf-php-src-2.1.0/src/wsf_wsdl.c(1226) [wsf_wsdl] Response envelope not found
因此,我的第一个想法是探查流量,尤其是工作(wsf_2.0.0/php5.2.x)和中断(wsf~2.1.0/php5.3)之间的SOAP标头
这是2.0.0版本(正在运行)的
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>my_username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
hashed(my_password)
</wsse:Password>
<wsse:Nonce>hashed</wsse:Nonce>
<wsu:Created>2012-07-26T20:40:26.991Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
和2.1.0(不工作/损坏)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>my_username</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">hashed(my_password)</wsse:Password>
<wsse:Nonce>hashed</wsse:Nonce>
<wsu:Created>2012-07-25T00:44:56.758Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
正如您所看到的,唯一的区别来自wsse:Security命名空间。(缺少xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/)
仅此而已。。。
根据调试日志检查第91行的rampart_in_handler.c说:
soap_header = axiom_soap_envelope_get_header(soap_envelope, env);
if(!soap_header)
{
/*No SOAP header, so no point of proceeding. FAIL*/
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart]SOAP header cannot be found.");
return AXIS2_FAILURE;
}
意思是。。。。soap_header为false。。但为什么呢?有没有聪明的人可以解释出了什么问题?
注1:我检查了从工作(2.0.0)发送给合作伙伴WS的策略,它似乎使用了AsymetricBinding。。。维奇很奇怪,因为在2.0.0版本中,我们没有提供任何证书或密钥。
注2:我还尝试将签名的用户名令牌与经典的WSPolicy对象数组参数一起使用-我创建了一个x509证书和私钥,然后使用函数加载这些文件,并使用数组参数将其加载到WSSecurity构造函数中。。。但我收到了同样的错误/Sniffing是一种痛苦b/c数据被加密或类似的东西(以这种方式似乎很正常)
注3:目前在Ubuntu10.04-3LTS上使用apt-get-预编译的php包进行了测试
救命!
我终于发现了问题,并修复了rampart_in_handler.c:91
问题来自回应,而不是请求。。。我通过tcp嗅探器进行了检查,来自合作伙伴WS的响应没有任何soap:Header。
无论是否符合标准,在上一个版本(2.0.0)中,它都在工作。因此,我决定稍微调整rampart_in_handler.c文件中的代码,以便在缺少soap头的情况下返回成功。。。
在我看来,如果我错了,PLZ会纠正我:
soapHeader响应的测试当然是添加到asymmetricBinding传输和新签名的usernametoken情况的b/c中的。但是,如果我们想在不签名的情况下使用usernametoken(通过基本策略.xml)AND,则在不使用任何soap:Header的情况下进行响应;那么rampart总是会返回一个失败。。。
此外,我还分析了脚本/文件夹下关于wsf处理响应的方式的php代码,并在这个文件上看到了函数wsf_process_response()
:下的wsf_wsdl.php
if($response_header_string && !empty($response_header_string)) {
$header_dom = new DomDocument();
$header_dom->preserveWhiteSpace = FALSE;
$header_dom->loadXML($response_header_string);
}
这意味着在php方面,当接收到数据时,wsf/php假设一个没有任何soapHeader的情况。。。(如果缺少soapHeader,就不会失败)超级奇怪!?
最后,我在wsf_wsdl_serialization.php
和wsf_wsdl_deserialization.php
文件上都发现了一个奇怪的错误。
例如,如果您计划用这样的字符串发送和/或接收参数/值:
"110% Sigma of something"
它将失败,并在序列化/取消序列化过程中创建segfault!
现在我在想为什么?但从第一个角度来看,"110%Sig.."包含"%S",而且它相当接近"%S"。。。
我认为这个bug就是这里提到的这个:
http://old.nabble.com/WSF-PHP-server-segfault-on-wsf_wsdl_serialization.php---td24329956.html
如果我把S改成D或其他什么,它就行了。。。
多么痛苦。。。