2

在继续之前要明确一点:不幸的是,这里不能选择使用 PHP 的内置 SOAP 类(生产服务器的 PHP 不是用它构建的,也不会是)。


我正在尝试使用 EWS 来允许我对完全外部服务器应用程序的用户进行身份验证。LDAP 身份验证已被禁止。我已通过Microsoft 自动发现工具http://www.testexchangeconnectivity.com/验证了我的 EWS wsdl 是否正确。可以在此处找到 WSDL 的内容:http: //pastebin.org/214070

服务器正在使用 SSL,并且正在使用“NTLM”的 EWS 的默认身份验证方法。

我尝试了网络上的各种代码示例,不幸的是我并不精通 XML、SOAP 或 cURL(这几乎是这里使用的所有技术)。我的代码的当前迭代如下所示:

<?php

include_once('./lib/nusoap.php');

$username = 'username@example.com';
$password = 'password';
$ews_url  = 'https://owa.example.com/EWS/Exchange.asmx';
$soapclient = new nusoap_client($service, true);
$soapclient->setCredentials($username, $password, 'ntlm');
$soapclient->setUseCurl(true);
$soapclient->useHTTPPersistentConnection();
$soapclient->setCurlOption(CURLOPT_USERPWD, $username.':'.$password);
$soapclient->soap_defencoding = 'UTF-8';

$params  = '<FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"';
$params += ' xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" Traversal="Shallow">';
$params += '    <ItemShape>';
$params += '        <t:BaseShape>IdOnly</t:BaseShape>';
$params += '        <t:AdditionalProperties>';
$params += '            <t:FieldURI FieldURI="message:From"/>';
$params += '            <t:FieldURI FieldURI="item:Subject"/>';
$params += '            <t:FieldURI FieldURI="message:IsRead"/>';
$params += '            <t:FieldURI FieldURI="item:DateTimeReceived"/>';
$params += '            <t:FieldURI FieldURI="calendar:Start"/>';
$params += '            <t:FieldURI FieldURI="calendar:End"/>';
$params += '            <t:FieldURI FieldURI="calendar:Location"/>';
$params += '            <t:FieldURI FieldURI="task:Status"/>';
$params += '            <t:FieldURI FieldURI="task:DueDate"/>';
$params += '        </t:AdditionalProperties>';
$params += '    </ItemShape>';
$params += '    <IndexedPageItemView Offset="0" MaxEntriesReturned="5" BasePoint="Beginning"/>';
$params += '    <ParentFolderIds>';
$params += '        <t:DistinguishedFolderId Id="inbox"/>';
$params += '    </ParentFolderIds>';
$params += '</FindItem>';

$operation = 'FindItem';
$namespace = '';
$soapAction = '';
$headers = false;
$result = $soapclient->call($operation, $params, $namespace, $soapAction, $headers);
echo '<pre>'; print_r($result); echo '</pre>';

if($soapclient->fault){
    echo 'FAULT: ';
    echo '<pre>'; print_r($result); echo '</pre>';
}else{
    $err = $soapclient->getError();
    if ($err) {
        echo '<p><b><u>Error</u>:</b><br />' . $err . '</p>';
    }else{
        echo 'Connection succeeded.';
    }
}
?>

我遇到的实际问题是 NuSOAP 返回一般错误消息:“没有在 WSDL 文档中定义的操作!”。从 WSDL 的外观来看,这似乎不正确,让我相信我在代码中遗漏了一些东西。如果我删除代码中的实际客户端调用 ($soapclient->call(...)),代码会打印出“连接成功。”,但无论是否尝试 NTLM 身份验证代码,它都会执行此操作。

我还尝试在我的开发机器上使用“php-ews”项目(即使相同的代码在生产服务器上不起作用)并且也无法在没有收到错误的情况下访问任何内容。

如果有人对任何这些技术有任何经验并且可能能够指出一些澄清(或可能的错误),我将不胜感激。如果我需要进一步澄清,请告诉我。

更新 1: 加载 WSDL 的一个错误似乎是 NTLM 身份验证。单独使用 cURL(无 NuSOAP)我能够访问 WSDL 文件并发现服务器正在重定向到不同的端点位置(.../EWS/Services.wsdl)。

不幸的是,我尝试使用 NuSOAP 库的 cURL 功能并通过 NuSOAP 设置相同的选项,但我仍然收到相同的通用错误消息,就好像 NuSOAP 只是无法查看/查看/访问 WSDL 文件一样。我相信它可能仍然是 NTLM 身份验证,因为 cURL 版本需要一些时间才能返回(NTLM 它是一个多步骤握手过程),而 NuSOAP 客户端代码会立即返回错误消息。

4

1 回答 1

2

您需要在这里查看一些内容。

  1. 您对实际soap_client 的调用存在错误。您在名为 $ews_url 的变量中定义了端点,但随后使用 $service 调用了构造函数。

  2. 你为什么要在 $xml 变量中的字符串中添加一个字符串 - 也许你急于要连接?(运算符:+ 与 .)

  3. 使用以下针对在 Java 中使用 EWS 的 Wiki 信息,似乎 Microsoft 在实现通用协议时又犯了错误。此 Wiki 中对 types.xsd 的修改实际上会导致问题,因此请忽略该更改,但下载 Services.wsdl 的本地副本并将其修改为指向您自己的服务器似乎可以正常工作。http://www.bedework.org/trac/bedework/wiki/ExchangeWS链接文本

只要您下载了 types.xsd、messages.xsd 和 Services.wsdl 的本地副本并修改了 Services.wsdl 文件以添加与您的服务器相关的所需信息,以下代码应该可以工作。确保这些文件的本地副本位于服务器上的同一文件夹中。

<?php
    include_once('./lib/nusoap.php');

    $username = 'username@example.com';
    $password = 'password';
    $endpoint = 'http://your.local.version/of/Services.wsdl';
    $wsdl = true;
    $soapclient = new nusoap_client($endpoint, $wsdl);

    $soapclient->setCredentials($username, $password, 'ntlm');

    $xml  = '<FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"';
    $xml .= ' xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" Traversal="Shallow">';
    $xml .= '   <ItemShape>';
    $xml .= '       <t:BaseShape>IdOnly</t:BaseShape>';
    $xml .= '       <t:AdditionalProperties>';
    $xml .= '           <t:FieldURI FieldURI="message:From"/>';
    $xml .= '           <t:FieldURI FieldURI="item:Subject"/>';
    $xml .= '           <t:FieldURI FieldURI="message:IsRead"/>';
    $xml .= '           <t:FieldURI FieldURI="item:DateTimeReceived"/>';
    $xml .= '           <t:FieldURI FieldURI="calendar:Start"/>';
    $xml .= '           <t:FieldURI FieldURI="calendar:End"/>';
    $xml .= '           <t:FieldURI FieldURI="calendar:Location"/>';
    $xml .= '           <t:FieldURI FieldURI="task:Status"/>';
    $xml .= '           <t:FieldURI FieldURI="task:DueDate"/>';
    $xml .= '       </t:AdditionalProperties>';
    $xml .= '   </ItemShape>';
    $xml .= '   <IndexedPageItemView Offset="0" MaxEntriesReturned="5" BasePoint="Beginning"/>';
    $xml .= '   <ParentFolderIds>';
    $xml .= '       <t:DistinguishedFolderId Id="inbox"/>';
    $xml .= '   </ParentFolderIds>';
    $xml .= '</FindItem>';

    $operation = 'FindItem';
    $result = $soapclient->call($operation, $xml);
    echo '<pre>'; print_r($result); echo '</pre>';
?>

解决方案似乎都源于拥有主要 SOAP 参考文件的本地副本,并修复了 Services.wsdl 文件。如果您有权访问 Exchange 服务器,则可能能够修改 Services.wsdl 文件,并且一切都可以按预期工作而没有所有这些麻烦。不幸的是,我无法验证这一点。

于 2010-10-22T16:23:16.930 回答