帮助使用Exchange 2010 EWS(API)和/或PHP';努索普图书馆?

帮助使用Exchange 2010 EWS(API)和/或PHP';努索普图书馆?,php,exchange-server,ntlm,nusoap,exchangewebservices,Php,Exchange Server,Ntlm,Nusoap,Exchangewebservices,在继续之前需要澄清的是:不幸的是,使用PHP的内置SOAP类在这里不是一个选项(生产服务器的PHP不是用它构建的,将来也不会) 我正在尝试使用EWS来验证完全外部服务器应用程序的用户。LDAP身份验证已被禁止。我已经通过Microsoft自动发现工具验证了我的EWS wsdl是否正确。WSDL的内容可在此处找到: 服务器正在使用SSL,并且正在使用“NTLM”EWS的默认身份验证方法 我在web上尝试过各种代码示例,不幸的是,我对XML、SOAP或cURL(这里使用的几乎都是这些技术)不是很精

在继续之前需要澄清的是:不幸的是,使用PHP的内置SOAP类在这里不是一个选项(生产服务器的PHP不是用它构建的,将来也不会)


我正在尝试使用EWS来验证完全外部服务器应用程序的用户。LDAP身份验证已被禁止。我已经通过Microsoft自动发现工具验证了我的EWS wsdl是否正确。WSDL的内容可在此处找到:

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

我在web上尝试过各种代码示例,不幸的是,我对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.';
    }
}
?>
call($operation、$params、$namespace、$soapAction、$headers);
回声';打印(结果);回声';
如果($soapclient->fault){
回音“错误:”;
回显“”;打印($result);回显“”;
}否则{
$err=$soapclient->getError();
如果($err){
回显“错误:
”。$err.

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

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

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

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


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

这里有几点您想看一下

  • 您对实际soap_客户端的调用中出现错误。您在一个名为$ews_url的变量中定义了端点,但随后使用$service调用了构造函数

  • 为什么要在$xml变量中的字符串中添加一个字符串?也许是因为匆忙,您想要连接?(操作员:+vs.)

  • 使用以下指向Java中EWS的Wiki信息,似乎Microsoft在实现公共协议时再次犯了错误。在这个Wiki中修改types.xsd实际上会导致一个问题,所以忽略这个更改,但是下载Services.wsdl的本地副本并修改它以指向您自己的服务器似乎可以正常工作

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

    调用($operation,$xml); 回声';打印(结果);回声'; ?>
    解决方案似乎都源于拥有主SOAP引用文件的本地副本,并修复Services.wsdl文件。如果您有权访问Exchange服务器,则可以修改Services.wsdl文件,并且一切都可以像预期的那样工作,而无需所有这些麻烦。不幸的是,我无法证实这一点。

    我在SourceForge上的NuSOAP“论坛”上创建了一个主题,希望窃笑者能够看到它并提供帮助。它还包含了更多的信息。可以在以下位置找到:我现在也在Exchange开发者论坛上开始了一个主题,希望能获得一些进一步的见解。WSDL和XSD文件的本地版本必须是web可访问的,否则NuSOAP将无法基于初始端点参数读取它们。例如,当尝试在端点上使用相对路径时,这是错误消息:“WSDL文件的错误路径://./messages.xsd”。要记住的东西。对libcurl或某些Windows服务/驱动程序的更新可能导致此脚本的互操作性问题。如果您在linux服务器上运行类似的代码,那么您需要确保您的curl/libcurl版本具有NTLMv2支持(>=v7.25),当然还有SSL。
    <?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>';
    ?>