【问题标题】:PHP SoapServer addSoapHeader ignored with SoapFault使用 SoapFault 忽略 PHP SoapServer addSoapHeader
【发布时间】:2013-03-27 09:36:19
【问题描述】:

我编写了一个接受基本身份验证凭据的 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-&gt;fault() 而不是throw new SoapFault 并没有什么不同。

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

提前致谢。

【问题讨论】:

    标签: php soap header soapserver soapfault


    【解决方案1】:

    这是 2013 年,我实际上遇到了完全相同的问题。好吧,现在是 2019 年,PHP 的当前版本是 7.3,而 7.4 正朝着我们迈出一大步。不幸的是,SoapServer 类在 SoapFault 案例中完全忽略了肥皂头。

    我编写了一个小变通方法来操作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。在故障情况下设置一个肥皂头

    不幸的是,没有花哨的 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 结构保存在字符串中并回显它。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的解决方法,很高兴听到人们在六年后仍在运行这个...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多