我已经编写了一个PHP SOAP服务,它接受http://www.whitemesa.com/soapauth.html中概述的基本身份验证凭据。为此,我在SOAPServer实例的处理程序类中定义了一个方法BasicAuth。这一切都运行得很好。
但是,当由于某种原因(用户名不正确,请求中没有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并没有什么不同。
我曾尝试自己构造错误对象,并将其作为常规响应返回,但我无法让PHP发送格式良好的响应。
提前谢谢。
发布于 2019-08-27 22:56:41
这是2013年,我实际上遇到了完全相同的问题。好吧,现在是2019年,PHP的当前版本是7.3,7.4即将到来,但不幸的是,在SoapFault中,SoapServer类完全忽略了soap头。
我写了一个小的变通方法来操作soap服务器的XML响应。对于每个有同样问题的人,这里有一个小的例子,如何解决它。
1.初始化Soap服务器
$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.在错误情况下设置soap标头
不幸的是,没有什么花哨的addSoapHeader函数可以简单地设置soap标头。在这种情况下,我们必须手动完成此操作。
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结构保存在字符串中并回显它。
希望这能对你有所帮助。
https://stackoverflow.com/questions/15655596
复制相似问题