HTTP-запрос не авторизован с использованием схемы аутентификации клиента Ntlm. Заголовок аутентификации, полученный от сервера, был NTLM. - PullRequest
49 голосов
/ 09 апреля 2010

Я знаю, что на SO много вопросов, похожих на эти, но я не смог найти ни одного для этой конкретной проблемы.

Сначала пара баллов:

  • У меня нет контроля над нашим сервером Sharepoint. Я не могу настроить параметры IIS.
  • Я считаю, что наша версия сервера IIS - IIS 7.0.
  • Наш сервер Sharepoint ожидает запросы через NTLM.
  • Наш сервер Sharepoint Server находится в том же домене, что и мой клиентский компьютер.
  • Я использую .NET Framework 3.5, Visual Studio 2008

Я пытаюсь написать простое консольное приложение для манипулирования данными Sharepoint с помощью веб-служб Sharepoint. Я добавил ссылку на сервис, и вот мой app.config:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="ListsSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="Transport">
                    <transport clientCredentialType="Ntlm" proxyCredentialType="Ntlm" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://subdomain.companysite.com/subsite/_vti_bin/Lists.asmx"
            binding="basicHttpBinding" bindingConfiguration="ListsSoap"
            contract="ServiceReference1.ListsSoap" name="ListsSoap" />
    </client>
</system.serviceModel>

Это мой код:

static void Main(string[] args)
{
    using (var client = new ListsSoapClient())
    {
        client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("username", "password", "domain");
        client.GetListCollection();
    }
}

Когда я вызываю GetListCollection (), выдается следующее MessageSecurityException :

The HTTP request is unauthorized with client authentication scheme 'Ntlm'.
The authentication header received from the server was 'NTLM'.

С внутренним WebException:

"The remote server returned an error: (401) Unauthorized."

Я пробовал различные привязки и различные настройки кода, чтобы попытаться правильно аутентифицироваться, но безрезультатно. Я перечислю их ниже.


Я пробовал следующие шаги:

Использование собственного имитатора Win32 перед созданием клиента

using (new Impersonator.Impersonator("username", "password", "domain"))
using (var client = new ListsSoapClient())
{
    client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("dpincas", "password", "domain");
    client.GetListCollection();
}

При этом выдается то же сообщение об ошибке.


Настройка TokenImpersonationLevel для учетных данных моего клиента

using (var client = new ListsSoapClient())
{
    client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
    client.GetListCollection();
}

При этом выдается то же сообщение об ошибке.


Использование режима безопасности = TransportCredentialOnly

<security mode="TransportCredentialOnly">
    <transport clientCredentialType="Ntlm" />
</security>

Это привело к другому сообщению об ошибке:

The provided URI scheme 'https' is invalid; expected 'http'.
Parameter name: via

Однако мне нужно использовать https, поэтому я не могу изменить схему URI.


Я пробовал некоторые другие комбинации, которые я не могу вспомнить, но я опубликую их, когда я это сделаю. Я действительно в остроумии здесь. Я вижу много ссылок в Google, которые говорят «переключиться на Kerberos», но мой сервер, похоже, принимает только NTLM, а не «Negotiate» (как было бы сказано, если он ищет Kerberos), так что, к сожалению, это не вариант .

Любая помощь, люди?

Ответы [ 10 ]

40 голосов
/ 09 апреля 2010

Visual Studio 2005

  1. Создание нового проекта консольного приложения в Visual Studio
  2. Добавить «веб-ссылку» в веб-сервис Lists.asmx.
    • Ваш URL, вероятно, будет выглядеть так: http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
    • Я назвал свою веб-ссылку: ListsWebService
  3. Напишите код в program.cs (у меня есть список проблем здесь)

Вот код.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace WebServicesConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ListsWebService.Lists listsWebSvc = new WebServicesConsoleApp.ListsWebService.Lists();
                listsWebSvc.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                listsWebSvc.Url = "http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx";
                XmlNode node = listsWebSvc.GetList("Issues");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}

Visual Studio 2008

  1. Создание нового проекта консольного приложения в Visual Studio
  2. Щелкните правой кнопкой мыши на References и добавьте Service Reference
  3. Введите URL-адрес службы Lists.asmx на вашем сервере.
    • Пример: http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
  4. Нажмите Go
  5. Нажмите ОК
  6. Внести следующие изменения кода:

Измените файл app.config с:

<security mode="None">
    <transport clientCredentialType="None" proxyCredentialType="None"
        realm="" />
    <message clientCredentialType="UserName" algorithmSuite="Default" />
</security>

Кому:

<security mode="TransportCredentialOnly">
  <transport clientCredentialType="Ntlm"/>
</security>

Измените ваш файл program.cs и добавьте следующий код в вашу основную функцию:

ListsSoapClient client = new ListsSoapClient();
client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
XmlElement listCollection = client.GetListCollection();

Добавить операторы использования:

using [your app name].ServiceReference1;
using System.Xml;

Ссылка: http://sharepointmagazine.net/technical/development/writing-caml-queries-for-retrieving-list-items-from-a-sharepoint-list

8 голосов
/ 15 октября 2010

После долгих проб и ошибок, за которыми последовал застойный период, пока я ждал возможности поговорить с нашими парнями на сервере, у меня наконец-то появилась возможность обсудить с ними проблему и спросить, не будут ли они против наша аутентификация на Sharepoint к Kerberos.

К моему удивлению, они сказали, что это не будет проблемой, и на самом деле это было легко сделать. Они включили Kerberos , и я изменил свой app.config следующим образом:

<security mode="Transport">
    <transport clientCredentialType="Windows" />
</security>

Для справки, моя полная запись serviceModel в моем app.config выглядит следующим образом:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="TestServerReference" closeTimeout="00:01:00" openTimeout="00:01:00"
             receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
             bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
             maxBufferSize="2000000" maxBufferPoolSize="2000000" maxReceivedMessageSize="2000000"
             messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
             useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                 maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="Transport">
                    <transport clientCredentialType="Windows" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://path/to/site/_vti_bin/Lists.asmx"
         binding="basicHttpBinding" bindingConfiguration="TestServerReference"
         contract="TestServerReference.ListsSoap" name="TestServerReference" />
    </client>
</system.serviceModel>

После этого все работало как шарм. Теперь я могу (наконец-то!) Использовать Sharepoint Web Services. Поэтому, если кто-то еще не может заставить свои веб-службы Sharepoint работать с NTLM, посмотрите, сможете ли вы убедить системных администраторов переключиться на Kerberos.

5 голосов
/ 24 февраля 2012

После многих ответов, которые не сработали, я наконец нашел решение, когда анонимный доступ отключен на сервере IIS. Наш сервер использует аутентификацию Windows, а не Kerberos. Это благодаря этой записи в блоге .

В web.config не было внесено никаких изменений.

На стороне сервера файл .SVC в папке ISAPI использует MultipleBaseAddressBasicHttpBindingServiceHostFactory

Атрибуты класса сервиса:

[BasicHttpBindingServiceMetadataExchangeEndpointAttribute]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class InvoiceServices : IInvoiceServices
{
...
}

На стороне клиента ключом к работе стали атрибуты безопасности привязки http:

EndpointAddress endpoint =
  new EndpointAddress(new Uri("http://SharePointserver/_vti_bin/InvoiceServices.svc"));
BasicHttpBinding httpBinding = new BasicHttpBinding();
httpBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
InvoiceServicesClient myClient = new InvoiceServicesClient(httpBinding, endpoint);
myClient.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation; 

(call service)

Я надеюсь, что это работает для вас!

3 голосов
/ 12 июля 2010

Если я правильно помню, существуют некоторые проблемы с добавлением веб-служб SharePoint в качестве VS2K8 «Справочник по службам». Вы должны добавить его как «Веб-справочник» старого стиля для правильной работы.

2 голосов
/ 18 июля 2010

У меня была эта проблема раньше.

client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

сделайте это с вашим прокси-сервером wcf перед вызовом.

2 голосов
/ 14 июля 2010

Я бы попытался подключиться к вашему сайту Sharepoint с помощью этого инструмента здесь .Если это работает, вы можете быть уверены, что проблема в вашем коде / конфигурации.Возможно, это не решит вашу проблему немедленно, но исключает, что с сервером что-то не так.Предполагая, что это не работает, я бы исследовал следующее:

  • Достаточно ли у вашего пользователя прав на сайте?
  • Существует ли прокси-сервер, который вмешивается?(Ваша конфигурация выглядит так, как будто есть прокси. Можете ли вы обойти его?)

Я думаю, что нет ничего плохого в использовании режима безопасности Transport , но я не такКонечно, насчет proxyCredentialType="Ntlm", возможно, это должно быть установлено на Нет .

2 голосов
/ 13 июля 2010

У меня была точно такая же проблема на прошлой неделе - Программа WCF странно ведет себя на одном сервере - почему?

Для меня решение было довольно простым. Sharepoint имеет собственный набор разрешений. Мой клиент попытался войти в систему как пользователь, которому явно не был предоставлен доступ к веб-сервису через панель администрирования Sharepoint.

Я добавил пользователя в белый список Sharepoint и взрыва - это просто сработало.

Даже если это не проблема, учтите, что

HTTP-запрос не авторизован с помощью схемы аутентификации клиента "Ntlm". Заголовок аутентификации, полученный от сервера, был «NTLM».

Означает (на английском языке), что у вас просто нет разрешения. Ваш протокол, вероятно, правильный - у вашего пользователя просто нет прав.

2 голосов
/ 13 июля 2010

У меня те же настройки, что и у вас, и у меня это отлично работает. Я думаю, что, возможно, проблема лежит где-то в вашей конфигурации мха или в вашей сети.

Вы сказали, что мох находится в том же домене, что и ваше приложение. Если у вас есть доступ к сайту с вашим пользователем (который зарегистрирован на вашем компьютере) ... вы пробовали:

client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
0 голосов
/ 25 февраля 2016

Эта проблема была еще более странной для нас. Все работало, если вы ранее посещали сайт sharepoint из браузера, перед тем как сделать SOAP-вызов. Однако, если бы вы сначала сделали вызов SOAP, мы бы выдавали вышеуказанную ошибку.

Мы смогли решить эту проблему, установив сертификат sharepoint на клиенте и добавив домен в локальные сайты интрасети.

0 голосов
/ 13 июля 2010

Попробуйте это

<client>
  <endpoint>
    <identity>
      <servicePrincipalName value="" />
    </identity>
  </endpoint>
</client>

Я сталкивался с этой ошибкой раньше, когда работал в веб-ферме, и это исправило ее для меня.

...