Помогите с Exchange 2010 EWS (API) и/или библиотекой PHP NuSOAP?

Просто чтобы прояснить, прежде чем продолжить: использование встроенного в PHP класса SOAP, к сожалению, здесь не вариант (PHP рабочего сервера не построен с ним и не будет).


Я пытаюсь использовать EWS, чтобы позволить мне аутентифицировать пользователей для полностью внешнего серверного приложения. Аутентификация LDAP запрещена. Я проверил правильность wsdl EWS с помощью http://www.testexchangeconnectivity.com/, инструмента автообнаружения Microsoft. . Содержимое WSDL можно найти здесь: http://pastebin.org/214070

Сервер использует SSL и использует метод проверки подлинности по умолчанию для EWS "NTLM".

Я пробовал различные примеры кода в Интернете, к сожалению, я не очень хорошо разбираюсь в XML, SOAP или cURL (это почти все используемые здесь технологии). Текущая итерация моего кода находится ниже:

<?php

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

$username = '[email protected]';
$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).

К сожалению, я пытался использовать возможность cURL библиотеки NuSOAP и устанавливать те же параметры через NuSOAP, и я все еще получаю то же общее сообщение об ошибке, как если бы NuSOAP просто не смог увидеть/просмотреть/доступ к файлу WSDL. Я полагаю, что это все еще может быть аутентификация NTLM, поскольку для возврата версии cURL требуется несколько секунд (NTLM - это многоэтапный процесс рукопожатия), тогда как клиентский код NuSOAP немедленно возвращает сообщение об ошибке.


person BrendonKoz    schedule 18.10.2010    source источник
comment
Я создал тему на форуме NuSOAP на SourceForge, надеясь, что, возможно, snichols увидят ее и смогут помочь. Он также содержит немного больше информации. Его можно найти по адресу: sourceforge.net/projects/nusoap/forums/ форум/193578/тема/   -  person BrendonKoz    schedule 20.10.2010
comment
Теперь я также начал тему на форумах разработчиков Exchange, чтобы, надеюсь, получить дополнительную информацию. social.technet.microsoft. com/Forums/en-US/   -  person BrendonKoz    schedule 21.10.2010


Ответы (1)


Есть несколько вещей, на которые вы захотите взглянуть.

  1. В вашем вызове фактического soap_client есть ошибка. Вы определили конечную точку в переменной с именем $ews_url, но затем вызвали конструктор с помощью $service.

  2. Почему вы добавляете строку к строке в своей переменной $xml - возможно, в спешке вы хотели вместо этого объединить? (операторы: + vs.)

  3. Используя следующую информацию Wiki, направленную на работу с EWS в Java, кажется, что Microsoft снова допустила ошибку в реализации общего протокола. Изменение типов.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 = '[email protected]';
    $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, и все могло бы работать должным образом без всех этих хлопот. Я не могу это проверить, к сожалению.

person BrendonKoz    schedule 22.10.2010
comment
Локальные версии файлов WSDL и XSD должны быть доступны через Интернет, иначе NuSOAP не сможет прочитать их на основе исходного параметра конечной точки. Например, при попытке использовать относительные пути на конечной точке это сообщение об ошибке: Неверный путь к файлу WSDL ://./messages.xsd. Что-то, что нужно иметь в виду. - person BrendonKoz; 25.10.2010
comment
Обновление либо для libcurl, либо для какой-либо службы/драйвера Windows могло вызвать проблемы взаимодействия с этим сценарием. Если вы запускаете аналогичный код на сервере Linux, убедитесь, что ваша версия curl/libcurl поддерживает NTLMv2 (›=v7.25), а также, очевидно, SSL. - person BrendonKoz; 26.07.2012