Я понимаю, что вы уже ответили на свой вопрос в контексте приложения, размещенного у поставщика, но для таких разработчиков, как я, которым нужен доступ к REST API с языка, не основанного на платформе .NET (и которые не могут написать свой проект как веб-приложение) Я хотел бы немного расширить тему. Недавно мне поручили написать приложение для 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's Back button to try your operation again."
}
}
}
person
Charles Grunwald
schedule
03.09.2014