首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用SoapFault忽略PHP SoapServer addSoapHeader

用SoapFault忽略PHP SoapServer addSoapHeader
EN

Stack Overflow用户
提问于 2013-03-27 17:36:19
回答 1查看 930关注 0票数 1

我已经编写了一个PHP SOAP服务,它接受http://www.whitemesa.com/soapauth.html中概述的基本身份验证凭据。为此,我在SOAPServer实例的处理程序类中定义了一个方法BasicAuth。这一切都运行得很好。

但是,当由于某种原因(用户名不正确,请求中没有BasicAuth头)导致身份验证失败时,我希望在响应中包含一个BasicChallenge头,如下所示:

代码语言:javascript
复制
<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>

以下代码不起作用(报头不会添加到响应中)。

代码语言:javascript
复制
$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并没有什么不同。

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

提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-08-27 22:56:41

这是2013年,我实际上遇到了完全相同的问题。好吧,现在是2019年,PHP的当前版本是7.3,7.4即将到来,但不幸的是,在SoapFault中,SoapServer类完全忽略了soap头。

我写了一个小的变通方法来操作soap服务器的XML响应。对于每个有同样问题的人,这里有一个小的例子,如何解决它。

1.初始化Soap服务器

代码语言:javascript
复制
$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标头。我们必须找出响应是否是故障。

代码语言:javascript
复制
$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.在错误情况下设置soap标头

不幸的是,没有什么花哨的addSoapHeader函数可以简单地设置soap标头。在这种情况下,我们必须手动完成此操作。

代码语言:javascript
复制
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();

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

希望这能对你有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15655596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档