我编写了一个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发送格式良好的响应。
提前致谢。
答案 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结构保存在字符串中并回显它。
希望这会有所帮助。