Загрузка данных с сайта со многократной проверкой подлинности с помощью клиентской объектной модели и веб-служб SharePoint 2010

Исходная статья опубликована в субботу 2 апреля 2011 г.

Тема этой записи блога уже сама объясняет, о чем мы сегодня поговорим. В этой записи блога рассматривается вопрос, который долго беспокоил меня лично и моих коллег. Я только недавно начал исследовать его, и так совпало, что я получил сообщение от кого-то с описанием решения этой проблемы.

 

Я описываю только самые общие части этого сценария, к ним можно добавить множество дополнительных вариаций. Задача состоит в загрузке данных с сайта SharePoint, на котором используется несколько поставщиков проверки подлинности. Предположим, что в этом сценарии один из них — поставщик утверждений Windows, а другой — любой другой поставщик (на основе форм или поставщик проверки подлинности SAML). Часто требуется загрузить данные с такого сайта с помощью клиентской модели или веб-служб SharePoint, но для этого применяется проверка подлинности. Проблема на этом этапе состоит в том, что даже если задать в запросе учетные данные Windows, при запросе данных доступ получить не удается.

 

Решение этой проблемы заключается в том, что для программного доступа к сайту SharePoint с несколькими поставщиками проверки подлинности с использованием учетных данных Windows требуется добавить дополнительный заголовок в запрос. Имя заголовка — X-FORMS_BASED_AUTH_ACCEPTED, а значение — "f". Добавление этого заголовка не так уж и очевидно для этих двух общих ситуаций, поэтому в остальной части данной зариси блога описывается, как сделать это с помощью кода.

 

При использовании клиентской объектной модели требуется добавить обработчик событий ExecutingWebRequest. Вот соответствующий пример кода:

 

//создание клиентского контекста

ClientContext ctx = new ClientContext(MixedUrlTxt.Text);

//настройка обработчика, добавляющего заголовок

ctx.ExecutingWebRequest +=

new EventHandler<WebRequestEventArgs>(ctx_MixedAuthRequest);

//задание учетных данныех Windows

ctx.AuthenticationMode = ClientAuthenticationMode.Default;

ctx.Credentials = System.Net.CredentialCache.DefaultCredentials;

//получение веб-сайта

Web w = ctx.Web;

//ЗАГРУЗКА СПИСКОВ СО ВСЕМИ СВОЙСТВАМИ

var lists = ctx.LoadQuery(w.Lists);

//выполнение запроса

ctx.ExecuteQuery();

//перечисление результатов

foreach (List theList in lists)

{

//выполнение каких-либо действий с каждым списком

}

 

А вот здесь происходит волшебство:

 

void ctx_MixedAuthRequest(object sender, WebRequestEventArgs e)

{

try

{

              //добавление заголовка, сообщающего SharePoint о необходимости использовать проверку подлинности Windows

              e.WebRequestExecutor.RequestHeaders.Add(

"X-FORMS_BASED_AUTH_ACCEPTED", "f");

       }

       catch (Exception ex)

       {

              MessageBox.Show("Ошибка установки заголовка проверки подлинности: " + ex.Message);

       }

}

 

Вот и все, мне кажется, что это довольно просто и понятно. Выполнение таких же действий со стандартной ссылкой веб-службы немного отличается. Для начала пройдемся по процессу добавления стандартной веб-ссылки на стиль на сайте SharePoint в проект Visual Studio 2010:

1. Щелкните правой кнопкой узел ссылки на службу и выберите команду "Добавить ссылку на службу".

2. Нажмите кнопку "Дополнительно" в нижней части диалогового окна.

3. Нажмите кнопку "Добавить веб-ссылку..." в нижней части следующего диалогового окна.

4. Введите URL-адрес веб-службы, которая будет использоваться, в поле URL-адреса. Например, чтобы добавить ссылку на веб-службу списков на сайте http://foo, в поле URL-адресе следует ввести следующее выражение: https://foo/_vti_bin/lists.asmx.

5. Нажмите клавишу ВВОД или кнопку с зеленой стрелкой для поиска ссылки веб-службы, затем введите имя ссылки в поле имени ссылки веб-службы и нажмите кнопку "Добавить ссылку".

 

Будут созданы ссылка и классы прокси для нее, но теперь нужно добавить дополнительный разделяемый класс для добавления заголовка в запрос веб-службы. Начните с добавления нового класса в проект и назовите его, как считаете нужным. Так как требуется добавить некоторое дополнительное поведение — добавление заголовка в запрос — это можно сделать в разделяемом классе. Это значит, что нужно скопировать как пространство имен, так и имя класса, используемые в прокси, созданном для веб-ссылки. Вот как это можно сделать:

 

1. Нажмите кнопку "Показать все файлы" в окне обозревателя решений в Visual Studio.

2. Щелкните значок "+" рядом со ссылкой веб-службы и разверните этот узел.

3. Щелкните значок "+" рядом с файлом Reference.map и разверните этот узел.

4. Дважды щелкните файл Reference.cs, чтобы открыть его.

5. Скопируйте пространство имен и вставьте его в свой класс.

6. Скопируйте имя класса, включая наследование, и вставьте его в свой класс в качестве имени класса. Класс ссылки веб-службы — это уже разделяемый класс, поэтому изменять его не нужно.

 

Вот пример того, как выглядит мой класс Reference.cs для моей ссылки веб-службы:

namespace ClientOmAuth.listsWS {

    using System;

    using System.Web.Services;

    using System.Diagnostics;

    using System.Web.Services.Protocols;

    using System.ComponentModel;

    using System.Xml.Serialization;

   

   

    /// <примечания/>

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]

    [System.Diagnostics.DebuggerStepThroughAttribute()]

    [System.ComponentModel.DesignerCategoryAttribute("code")]

    [System.Web.Services.WebServiceBindingAttribute(Name="ListsSoap", Namespace="http://schemas.microsoft.com/sharepoint/soap/")]

    public partial class Lists : System.Web.Services.Protocols.SoapHttpClientProtocol {

А вот то, что я вставил в созданный класс:

namespace ClientOmAuth.listsWS

{

       public partial class Lists : System.Web.Services.Protocols.SoapHttpClientProtocol

       {

       }

}

Можно заметить, что совпадают как пространство имен, так и имена классов, и что оба класса наследуются от одного базового типа.

 

Теперь нужно переопределить метод GetWebRequest, чтобы можно было добавить заголовок. Этого можно добиться, просто добавив данный код в разделяемый класс:

protected override System.Net.WebRequest GetWebRequest(Uri uri)

{

       System.Net.WebRequest wr = null;

       try

       {

              wr = base.GetWebRequest(uri);

              wr.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");

       }

       catch (Exception ex)

       {

              //здесь обрабатываются ошибки

       }

                          

       return wr;

}

 

Код для загрузки данных с помощью веб-службы аналогичен использованию любой проверки подлинности Windows на сайте SharePoint:

 

//создание прокси веб-службы и настройка его для использования моих учетных данных Windows

listsWS.Lists lws = new listsWS.Lists();

lws.UseDefaultCredentials = true;

//получение коллекции списков

XmlNode xLists = lws.GetListCollection();

//перечисление результатов

foreach (XmlNode xList in xLists.ChildNodes)

{

//выполнение каких-либо действий с каждым списком

}

Вот и все. Такой подход можно применять и при загрузке данных с помощью REST, используя методику, описанную мною здесь: http://blogs.technet.com/b/speschka/archive/2010/09/25/retrieving-rest-data-in-a-claims-based-auth-site-in-sharepoint-2010.aspx.

 

Это локализованная запись блога. Исходная статья доступна по адресу Retrieving Data from a Multi Auth Site Using the Client OM and Web Services in SharePoint 2010