【问题标题】:The HTTP request is unauthorized with client authentication scheme 'Ntlm' The authentication header received from the server was 'NTLM'HTTP 请求未使用客户端身份验证方案“Ntlm”未经授权从服务器接收到的身份验证标头为“NTLM”
【发布时间】:2011-02-06 05:22:12
【问题描述】:

我知道关于 SO 有很多与此类似的问题,但我找不到针对此特定问题的问题。

先说几点:

  • 我对我们的 Sharepoint 服务器无法控制。我无法调整任何 IIS 设置。
  • 我相信我们的 IIS 服务器版本是 IIS 7.0。
  • 我们的 Sharepoint 服务器正在通过 NTLM 预测请求。
  • 我们的 Sharepoint Server 与我的客户端计算机位于同一域中。
  • 我正在使用 .NET Framework 3.5、Visual Studio 2008

我正在尝试编写一个简单的控制台应用程序来使用 Sharepoint Web 服务来操作 Sharepoint 数据。我添加了Service Reference,下面是我的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 Impersonator

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,而不是“协商”(如果它正在寻找 Kerberos),所以很遗憾这不是一个选项.

有什么帮助吗,伙计们?

【问题讨论】:

标签: c# .net sharepoint authentication ntlm


【解决方案1】:

Visual Studio 2005

  1. 在 Visual Studio 中创建一个新的控制台应用程序项目
  2. 向 Lists.asmx Web 服务添加“Web 引用”。
    • 您的 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. 右键单击引用并添加服务引用
  3. 在您的服务器上输入 Lists.asmx 服务的 URL
    • 例如:http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
  4. 点击前往
  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 文件并将以下代码添加到您的 Main 函数中:

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 语句:

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

参考:http://sharepointmagazine.net/technical/development/writing-caml-queries-for-retrieving-list-items-from-a-sharepoint-list

【讨论】:

  • @Kit Menke,我从默认配置中编辑了 app.config,因为我收到此错误:HTTP 请求未经授权,客户端身份验证方案“匿名”。从服务器收到的身份验证标头是“NTLM”。我需要将 app.config 中的 元素从 clientCredentialType="None" proxyCredentialType="None" 更改为 clientCredentialType="Ntlm" proxyCredentialType="Ntlm"。然而,这一切只是给了我一个不同的错误信息:-)
  • 还要注意他访问列表的方式不同——我从不在使用 SP Web 服务的代码中引用soap。我只是在 Visual Studio 中添加 Web 引用并像上面的 Kit 一样访问它。
  • 感谢您更新您的示例,Kit。您的示例目前正是我在最新版本的代码中所拥有的。我相信这个问题实际上是我们的 MOSS 设置的问题,与代码无关 :-( 不幸的是,我仍在等待服务器人员的回复,以找出问题所在。我的目的是更新这个一旦他们回复我关于他们修复的问题,就会向“服务器”解决方案提出问题。
  • 请将相同的答案粘贴到stackoverflow.com/questions/4558922/…,我会标记为答案!
【解决方案2】:

经过大量的尝试和错误,然后在等待机会与我们的服务器人员交谈时停滞不前,我终于有机会与他们讨论问题并询问他们是否不介意切换我们将 Sharepoint 身份验证转移到 Kerberos。

令我惊讶的是,他们说这不是问题,而且实际上很容易做到。 他们启用了 Kerberos,我修改了我的 app.config,如下所示:

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

作为参考,我的 app.config 中的完整 serviceModel 条目如下所示:

<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 服务了。因此,如果其他人无法让他们的 Sharepoint Web 服务与 NTLM 一起使用,请查看您是否可以说服系统管理员切换到 Kerberos。

【讨论】:

    【解决方案3】:

    在多次回答无效后,终于在IIS服务器上禁用匿名访问时找到了解决方案。我们的服务器使用的是 Windows 身份验证,而不是 Kerberos。这要感谢this blog posting

    未对 web.config 进行任何更改。

    在服务器端,ISAPI文件夹中的.SVC文件使用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)
    

    我希望这对你有用!

    【讨论】:

      【解决方案4】:

      如果我没记错的话,将 SharePoint Web 服务添加为 VS2K8“服务参考”存在一些问题。您需要将其添加为旧式“Web 参考”才能正常工作。

      【讨论】:

      • 谢谢!我总是忘记这种老式对话框的存在。
      【解决方案5】:

      我的设置和你一样,这对我来说很好用。我认为问题可能出在您的苔藓配置或网络上。

      您说 moss 与您的应用程序位于同一个域中。如果您可以通过您的用户(即登录到您的机器)访问该站点...您是否尝试过:

      client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
      

      【讨论】:

        【解决方案6】:

        上周我遇到了完全相同的问题 - WCF program behaves strangely on one server - why?

        对我来说,解决方案相当简单。 Sharepoint 有自己的一组权限。我的客户尝试以未通过 Sharepoint 的管理面板明确授予访问 Web 服务的用户身份登录。

        我将用户添加到 Sharepoint 的白名单中,然后砰的一声——它确实有效。

        即使这不是问题,请注意

        HTTP 请求未经客户端身份验证方案“Ntlm”的授权。从服务器收到的身份验证标头是“NTLM”。

        表示(英文)您根本没有权限。您的协议可能是正确的 - 您的用户只是没有权限。

        【讨论】:

        • 在某些情况下这可能是正确的,但在我的情况下,我拥有完全的权限,至少根据服务器人员的说法。不幸的是,这个错误信息(显然)意味着很多不同的东西!
        • 根据内部共享点权限数据库登录的用户对您尝试拉取的共享点项目具有完全权限?
        • 这个管理面板在哪里明确授予用户访问网络服务的权限?
        【解决方案7】:

        我会尝试使用此工具here 连接到您的 Sharepoint 站点。如果可行,您可以确定问题出在您的代码/配置中。这可能不会立即解决您的问题,但它排除了服务器有问题。假设它不起作用,我将调查以下内容:

        • 您的用户在网站上真的拥有足够的权限吗?
        • 是否有代理干扰? (你的配置看起来有点像有代理,能绕过吗?)

        我认为使用安全模式Transport没有什么问题,但我不太确定proxyCredentialType="Ntlm",也许应该设置为None

        【讨论】:

        • 很棒的工具!不幸的是,无论我是否选择了“当前用户”或我的域用户名/密码,它都会产生完全相同的错误。这个问题在这一点上有点老了,事实上我确实怀疑这是一个服务器问题并联系了我们的服务器管理员。他们有一个可以正常工作的开发站点,他们向我保证他们会在我们的实时站点上“调查”这个问题。仍在等待他们的回音...
        【解决方案8】:

        我以前也遇到过这个问题。

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

        在拨打电话之前对您的 wcf 代理执行此操作。

        【讨论】:

          【解决方案9】:

          试试这个

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

          我之前在 webfarm 中工作时遇到过这个错误,这已经为我解决了。

          【讨论】:

            【解决方案10】:

            这个问题对我们来说更奇怪。如果您之前在进行 SOAP 调用之前从浏览器访问过共享点站点,那么一切正常。但是,如果您先进行 SOAP 调用,我们会抛出上述错误。

            我们能够通过在客户端上安装共享点证书并将域添加到本地 Intranet 站点来解决此问题。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-12-02
              • 2011-06-22
              • 2013-03-12
              • 2014-12-07
              • 2012-09-24
              • 1970-01-01
              相关资源
              最近更新 更多