帮助Exchange 2010 EWS(API)和/或PHP的NuSOAP库?

时间:2010-10-18 19:03:19

标签: php exchange-server ntlm nusoap exchangewebservices

在继续之前要明确一点:遗憾的是,使用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-&gt; call(...)),代码将打印出“Connection succeeded。”,但无论是否使用NTLM身份验证代码,都会执行此操作。

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

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

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

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

1 个答案:

答案 0 :(得分:2)

这里有一些你想看的东西。

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

  2. 为什么要在$ xml变量中的字符串中添加一个字符串 - 也许是你想要连接的匆忙? (运营商:+ vs。)

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

  4. 以下代码应该可以使用,只要您下载了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文件,并且可以的所有内容都按预期工作,而不会出现所有这些麻烦。不幸的是,我无法验证这一点。