使用SoapFault忽略PHP SoapServer addSoapHeader

时间:2013-03-27 09:36:19

标签: php soap header soapserver soapfault

我编写了一个PHP SOAP服务,它接受http://www.whitemesa.com/soapauth.html中概述的基本身份验证凭据。我通过在BasicAuth实例的处理程序类中定义方法SOAPServer来完成此操作。一切正常。

但是,当身份验证由于某种原因失败(用户名不正确,请求中没有BasicAuth标头)时,我想在我的回复中包含BasicChallenge标头,如下所示:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header>
      <h:BasicChallenge xmlns:h="http://soap-authentication.org/basic/2001/10/"
                        SOAP-ENV:mustUnderstand="1">
         <Realm>Realm</Realm>
      </h:BasicChallenge>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Client</faultcode>
         <faultstring>Authentication failed</faultstring>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

以下代码不起作用(标题未添加到响应中)。

$soapServer->addSoapHeader(new SoapHeader("http://soap-authentication.org/basic/2001/10/", "BasicChallenge", array("Realm" => "Realm"), true));
throw new SoapFault("Client", "Authentication Failed");

调用$soapServer->fault()代替throw new SoapFault并没有什么区别。

我自己尝试构建Fault对象,并将其作为常规响应返回,但我无法让PHP发送格式良好的响应。

提前致谢。

1 个答案:

答案 0 :(得分:0)

这是2013年,实际上我遇到了完全相同的问题。好吧,这是2019年,PHP的当前版本是7.3和7.4,这是我们迈出的重要一步。不幸的是,在SoapFault情况下,SoapServer类完全忽略了肥皂头。

我写了一个小的解决方法来操纵肥皂服务器的XML响应。对于遇到同样问题的每个人,这是一个小例子,说明如何解决。

1。初始化您的Soap Server

$server = new SoapServer($wsdl, $options);

ob_start();
$server->setObject($service);
$server->handle();
$response = ob_get_contents();
ob_end_clean();

实际上,我们正在做一个简单的初始化。除了简单地返回内容外,我们还使用输出缓冲功能拦截xml响应。的结果是$response中的xml字符串。

2。找出响应是否有误

实际上,SoapServer类正在添加soap标头(如果它是有效的响应)。我们必须找出响应是否错误。

$doc = new DOMDocument();
$doc->loadXML($response);

$xpath = new DOMXPath($doc);
$isFault = $xpath->query('//*[local-name()="Fault"]')->length;

只需将响应xml字符串加载到DOMDocument类中。从现在开始,我们能够使用DOM函数访问xml元素。为了更好地处理,我使用了DOMXPath类。当然,也可以使用DOMDocument类确定XML节点。 $isFault变量可用于下一步。

3。如果出现故障,请设置肥皂标头

不幸的是,没有简单的设置肥皂标题的addSoapHeader功能。在这种情况下,我们必须手动进行操作。

if ($isFault) {
    $header = $doc->createElementNS('http://schemas.xmlsoap.org/soap/envelope/', 'Header');
    $body = $doc->getElementsByTagNameNS('http://schemas.xmlsoap.org/soap/envelope/', 'Body')->item(0);

    $realm = $doc->createElementNS('http://soap-authentication.org/basic/2001/10/', 'h:Realm');
    $basicChallenge = $doc->createElementNS('http://soap-authentication.org/basic/2001/10/', 'h:BasicChallenge');

    $basicChallenge->appendChild($realm);
    $header->appendChild($basicChallenge);

    $doc->documentElement->insertBefore($header, $body);
}

$xmlResponse = $doc->saveXML($doc->documentElement);

header('Content-Length: ' . strlen($xmlResponse));
echo $xmlResponse;
exit();

在发生故障的情况下,我们将创建标头元素并添加所需的所有子节点。如果附加了一切,则将标头插入正文之前,将新的xml结构保存在字符串中并回显它。

希望这会有所帮助。