Ответ 1
Я понимаю, что вы уже ответили на свой вопрос в контексте приложения, поддерживающего провайдер, но для таких разработчиков, как я, которым необходимо получить доступ к REST API с языка, не основанного на .NET Framework (и кто не может напишите их проект как веб-приложение). Я хотел бы расширить эту тему немного больше. Мне было поручено написать приложение iPad недавно, требующее этой функции, и закончил обратное проектирование следующим образом:
Шаг 1 - Аутентификация
Не собираюсь на самом деле покрывать это, так как есть много примеры онлайн, которые демонстрируют более общие методы. Обычно библиотеки Microsoft.SharePoint.Client
используют аутентификацию на основе утверждений при работе с SharePoint Online, при этом маркер запрашивается через конечную точку, найденную по адресу: https://login.microsoftonline.com/RST2.srf
Шаг 2 - Приобретение дайджест-запроса (немой подход)
Если вы чувствуете себя ленивым, вы всегда можете взять свои файлы cookie, прошедшие проверку подлинности, сделать запрос GET на домашнюю страницу целевой сети и использовать регулярное выражение, например:
/(<input (?:[^>]*?)name="?__REQUESTDIGEST"?(?:[^>]*?)\/>)/i
чтобы очистить HTML от ответа. Оттуда просто нужно извлечь атрибут value
для вашего дайджеста.
Шаг 2 - Получение дайджеста запроса (подход SOAP)
Библиотеки CSOM в настоящее время используют конечную точку SOAP при приобретении дайджеста запроса, который он использует для своих вызовов API. Вы можете сделать то же самое, сделав запрос SOAP к веб-службе $(SPWebUrl)/_vti_bin/sites.asmx
, как показано ниже:
POST $(SPWebUrl)/_vti_bin/sites.asmx HTTP/1.1
Content-Type: text/xml
SOAPAction: http://schemas.microsoft.com/sharepoint/soap/GetUpdatedFormDigestInformation
X-RequestForceAuthentication: true
Host: $(SPSiteHostname)
Expect: 100-continue
Accept-Encoding: gzip, deflate
Cookie: $(Authenticated Cookies - Either "FedAuth=...; rtFa=..." or "SPOIDCRL=...")
Content-Length: $(Whatever)
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetUpdatedFormDigestInformation xmlns="http://schemas.microsoft.com/sharepoint/soap/" />
</soap:Body>
</soap:Envelope>
При успешном выполнении тело ответа будет выглядеть примерно так:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetUpdatedFormDigestInformationResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<GetUpdatedFormDigestInformationResult>
<DigestValue>0x1122334455 ... FF,27 Jul 2015 03:06:54 -0000</DigestValue>
<TimeoutSeconds>1800</TimeoutSeconds>
<WebFullUrl>$(SPWebUrl)</WebFullUrl>
<LibraryVersion>16.0.3208.1222</LibraryVersion>
<SupportedSchemaVersions>14.0.0.0,15.0.0.0</SupportedSchemaVersions>
</GetUpdatedFormDigestInformationResult>
</GetUpdatedFormDigestInformationResponse>
</soap:Body>
</soap:Envelope>
В этот момент вы можете просто извлечь свой дайджест запроса из блока DigestValue
.
Шаг 2 - Приобретение дайджеста запроса (подход REST)
Последний подход, о котором я знаю, использует запрос OData, сделанный в конечной точке $(SPWebUrl)/_api/contextinfo
:
POST $(SPWebUrl)/_api/contextinfo HTTP/1.1
Host: $(SPSiteHostname)
DataServiceVersion: 3.0
Accept: application/json; odata=nometadata
Content-Type: application/json; odata=verbose
Cookie: $(Authenticated Cookies)
Content-Length: 2
{}
При успешном выполнении, тело ответа будет выглядеть следующим образом:
{
"FormDigestTimeoutSeconds" : 1800,
"FormDigestValue" : "0x1122334455 ... FF,27 Jul 2015 03:06:54 -0000",
"LibraryVersion" : "16.0.4230.1217",
"SiteFullUrl" : "$(SPSiteUrl)",
"SupportedSchemaVersions" : ["14.0.0.0", "15.0.0.0"],
"WebFullUrl" : "$(SPWebUrl)"
}
Затем может быть извлечен дайджест запроса из свойства FormDigestValue
.
Шаг 2 - Приобретение дайджеста запросов (подход CSOM)
Если вы используете CSOM, у вас есть функциональность для работы с этим встроенным. (возможно, JSOM тоже, если он не использует вход __REQUESTDIGEST) Microsoft.SharePoint.Client.ClientContext
использует SOAP-подход для управления сводок запросов и публично раскрывает эту функцию с помощью метода GetFormDigestDirect
.
ClientContext clientContext = new ClientContext(webUrl);
// ...
FormDigestInfo formDigest = clientContext.GetFormDigestDirect();
// X-RequestDigest header value
string headerValue = formDigest.DigestValue;
// Digest expiration
DateTime expirationDate = formDigest.Expiration;
Замечания по использованию. Хотя ClientContext
поддерживает и повторно использует кэшированный формуляр для своих запросов, этот метод не дает вам доступ к этому кешированному значению. Вместо этого этот метод запрашивает новый рецепт формы с каждым вызовом, поэтому вы захотите настроить свой собственный механизм кеширования, чтобы повторно использовать неиспользуемые дайджесты для нескольких запросов.
Шаг 2 - Приобретение дайджеста запроса (подход JSOM)
Если вы используете JSOM API и не имеете доступа к входному значению __REQUESTDIGEST
, вы можете получить доступ к кэшированному дайджесту ClientContext
с помощью следующие расширения. (Благодаря bdimag для указания кеша)
Шаг 3 - Получение новых дайджетов запросов
Предполагая, что вы используете дайджест запроса до истечения TimeoutSeconds
, действительный запрос REST выполнен следующим образом:
POST $(SPWebUrl)/_api/web/lists/getByTitle('MyList')/getchanges HTTP/1.1
Host: $(SPSiteHostname)
DataServiceVersion: 3.0
Accept: application/json; odata=nometadata
Content-Type: application/json; odata=verbose
X-RequestDigest: $(Request Digest)
Cookie: $(Authenticated Cookies)
Content-Length: 140
{
"query" : {
"__metadata" : {
"type" : "SP.ChangeQuery"
},
"Add" : "True",
"Item" : "True",
"Update" : "True"
}
}
должен привести к успешному ответу. Если вы проверите заголовки этого ответа, вы найдете что-то вроде:
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: application/json;odata=fullmetadata;streaming=true;charset=utf-8
...
X-RequestDigest: 0xAABBCC...00,03 Sep 2014 18:09:34 -0000
...
Извлечение заголовка ответа X-RequestDigest
позволит вам использовать его в последующем вызове. (Я предполагаю, что таймаут начинается с момента вашего нового ответа + $(TimeoutSeconds)
из исходного запроса дайджеста, но я еще не подтвердил)
К сожалению, заголовок X-RequestDigest
возвращается только запросами REST, которые на самом деле требуют дайджест запроса. Вы не получите заголовок для запросов, в которых необработанный дайджест запроса, например: $(SPWebUrl)/_api/web/lists/getByTitle('MyList')/items
. Если вам понадобится новый дайджест после истечения срока оригинала, вам нужно будет сделать еще один запрос в веб-службу $(SPWebUrl)/_vti_bin/sites.asmx
.
Шаг??? - Обработка ошибок
Несколько примеров ответов, когда наши запросы терпят неудачу:
Следующий ответ приходит из запроса REST, сделанного в конечную точку $(SPWebUrl)/_api/contextinfo
. (не указаны файлы cookie для проверки подлинности)
HTTP/1.1 403 Forbidden
Cache-Control: private, max-age=0
Content-Type: application/json;odata=nometadata;charset=utf-8
...
Server: Microsoft-IIS/8.5
X-SharePointHealthScore: 0
X-Forms_Based_Auth_Required: $(SPRootSiteUrl)/_forms/default.aspx?ReturnUrl=/_layouts/15/error.aspx&Source=%2f_vti_bin%2fclient.svc%2fcontextinfo
X-Forms_Based_Auth_Return_Url: $(SPRootSiteUrl)/_layouts/15/error.aspx
X-MSDAVEXT_Error: 917656; Access+denied.+Before+opening+files+in+this+location%2c+you+must+first+browse+to+the+web+site+and+select+the+option+to+login+automatically.
DATASERVICEVERSION: 3.0
X-AspNet-Version: 4.0.30319
X-IDCRL_AUTH_PARAMS_V1: IDCRL Type="BPOSIDCRL", EndPoint="$(SiteRelativeUrl)/_vti_bin/idcrl.svc/", RootDomain="sharepoint.com", Policy="MBI"
...
Date: Wed, 12 Aug 2015 02:27:35 GMT
Content-Length: 201
{
"odata.error" : {
"code" : "-2147024891, System.UnauthorizedAccessException",
"message" : {
"lang" : "en-US",
"value" : "Access denied. You do not have permission to perform this action or access this resource."
}
}
}
Далее ответ, исходящий из запроса REST, сделанного с помощью дайджеста с истекшим запросом (обратите внимание на заголовок X-RequestDigest
, указанный в ответе.. Не уверен, что это можно использовать, но это стоит того):
HTTP/1.1 403 FORBIDDEN
Cache-Control: private, max-age=0
Content-Type: application/json;odata=fullmetadata;charset=utf-8
...
Server: Microsoft-IIS/8.5
Set-Cookie: rtFa=$(RtfaAuthCookie)
Set-Cookie: FedAuth=$(FedAuth)
X-SharePointHealthScore: 0
X-RequestDigest: 0x19EFFF80617AB2E48B0A9FF0ABA1440B5301E7445F3859177771BF6A39C7E4A74643108D862505A2C99350B0EDB871EF3DDE960BB68060601268818027F04956,12 Aug 2015 02:39:22 -0000
DATASERVICEVERSION: 3.0
X-AspNet-Version: 4.0.30319
...
Date: Wed, 12 Aug 2015 02:39:22 GMT
Content-Length: 253
{
"odata.error" : {
"code" : "-2130575251, Microsoft.SharePoint.SPException",
"message" : {
"lang" : "en-US",
"value" : "The security validation for this page is invalid and might be corrupted. Please use your web browser Back button to try your operation again."
}
}
}