Загрузка данных с сайта со многократной проверкой подлинности с помощью клиентской объектной модели и веб-служб 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-адреса. Например, чтобы добавить ссылку на веб-службу списков на сайте https://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="https://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, используя методику, описанную мною здесь: https://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