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

发布于 2024-08-28 06:39:25 字数 3655 浏览 4 评论 0原文

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

首先有几点:

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

我正在尝试编写一个简单的控制台应用程序来使用 Sharepoint Web 服务操作 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 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,它会说),所以不幸的是,这不是一个选项。

各位有什么帮助吗?

I know there's a lot of questions on SO similar to this, but I couldn't find one for this particular issue.

A couple of points, first:

  • I have no control over our Sharepoint server. I cannot tweak any IIS settings.
  • I believe our IIS server version is IIS 7.0.
  • Our Sharepoint Server is anticipating requests via NTLM.
  • Our Sharepoint Server is on the same domain as my client computer.
  • I am using .NET Framework 3.5, Visual Studio 2008

I am trying to write a simple console app to manipulate Sharepoint data using Sharepoint Web Services. I have added the Service Reference, and the following is my 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>

This is my code:

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

When I call GetListCollection(), the following MessageSecurityException gets thrown:

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

With an inner WebException:

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

I've tried various bindings and various code tweaks to try to authenticate properly, but to no avail. I'll list those below.


I've tried the following steps:

Using a native Win32 Impersonator before creating the client

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

This produced the same error message.


Setting TokenImpersonationLevel for my client credentials

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

This produced the same error message.


Using security mode=TransportCredentialOnly

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

This resulted in a different error message:

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

However, I need to use https, so I cannot change my URI scheme.


I've tried some other combinations that I can't remember, but I'll post them when I do. I'm really at wits end here. I see a lot of links on Google that say "switch to Kerberos", but my server seems to only be accepting NTLM, not "Negotiate" (as it would say if it was looking for Kerberos), so that is unfortunately not an option.

Any help out there, folks?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

半夏半凉 2024-09-04 06:39:25

Visual Studio 2005

  1. 在 Visual Studio 中创建一个新的控制台应用程序项目
  2. 将“Web 引用”添加到 Lists.asmx Web 服务。
    • 您的网址可能如下所示: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. 将 URL 输入到服务器上的 Lists.asmx 服务
    • 例如:http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
  4. 单击“Go”(执行
  5. ) 单击“OK”
  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-retriving-list-items-from-a-sharepoint-列表

Visual Studio 2005

  1. Create a new console application project in Visual Studio
  2. Add a "Web Reference" to the Lists.asmx web service.
    • Your URL will probably look like: http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
    • I named my web reference: ListsWebService
  3. Write the code in program.cs (I have an Issues list here)

Here is the code.

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. Create a new console application project in Visual Studio
  2. Right click on References and Add Service Reference
  3. Put in the URL to the Lists.asmx service on your server
    • Ex: http://servername/sites/SiteCollection/SubSite/_vti_bin/Lists.asmx
  4. Click Go
  5. Click OK
  6. Make the following code changes:

Change your app.config file from:

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

To:

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

Change your program.cs file and add the following code to your Main function:

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();

Add the using statements:

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

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

情绪少女 2024-09-04 06:39:25

经过大量的尝试和错误,然后是一段停滞期,等待与我们的服务器人员交谈的机会,我终于有机会与他们讨论问题并询问他们是否介意切换我们的 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。

After a lot of trial and error, followed by a stagnant period while I waited for an opportunity to speak with our server guys, I finally had a chance to discuss the problem with them and asked them if they wouldn't mind switching our Sharepoint authentication over to Kerberos.

To my surprise, they said this wouldn't be a problem and was in fact easy to do. They enabled Kerberos and I modified my app.config as follows:

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

For reference, my full serviceModel entry in my app.config looks like this:

<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>

After this, everything worked like a charm. I can now (finally!) utilize Sharepoint Web Services. So, if anyone else out there can't get their Sharepoint Web Services to work with NTLM, see if you can convince the sysadmins to switch over to Kerberos.

你怎么这么可爱啊 2024-09-04 06:39:25

经过许多不起作用的答案后,我终于在 IIS 服务器上禁用匿名访问时找到了解决方案。我们的服务器使用 Windows 身份验证,而不是 Kerberos。这要归功于这篇博文

未对 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)

我希望这对您有用!

After many answers that did not work, I finally found a solution when Anonymous access is Disabled on the IIS server. Our server is using Windows authentication, not Kerberos. This is thanks to this blog posting.

No changes were made to web.config.

On the server side, the .SVC file in the ISAPI folder uses MultipleBaseAddressBasicHttpBindingServiceHostFactory

The class attributes of the service are:

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

On the client side, the key that made it work was the http binding security attributes:

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)

I hope this works for you!

难得心□动 2024-09-04 06:39:25

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

If I recall correctly, there are some issues with adding SharePoint web services as a VS2K8 "Service Reference". You need to add it as an old-style "Web Reference" to work properly.

萌酱 2024-09-04 06:39:25

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

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

在进行调用之前对您的 wcf 代理执行此操作。

I have had this issue before.

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

do this against your wcf proxy before making the call.

情徒 2024-09-04 06:39:25

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

您说 moss 与您的应用程序驻留在同一域中。如果您可以使用您的用户(登录到您的计算机)访问该站点...您是否尝试过:

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

I have the same setup that you do, and this works fine for me. I think that maybe the problem lies somewhere on your moss configuration or on your network.

You said that moss resides on the same domain as your application. If you have access to the site with your user (that is logged into your machine)... have you tried:

client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
烟火散人牵绊 2024-09-04 06:39:25

上周我遇到了完全相同的问题 - WCF 程序在一台服务器上行为异常- 为什么?

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

我将用户添加到 Sharepoint 的白名单中,然后就成功了。

即使这不是问题,请注意,

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

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

I had exactly the same issue last week - WCF program behaves strangely on one server - why?

For me the solution was rather simple. Sharepoint has its own set of permissions. My client tried to log on as a user that wasn't explicitly given access to the webservice through Sharepoint's administration panel.

I added the user to Sharepoint's whitelist and bang - it just worked.

Even if that isn't the issue, please note that

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

Means (in English) that you simply don't have permission. Your protocol is probably right - your user just doesn't have permissions.

画尸师 2024-09-04 06:39:25

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

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

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

I would try to connect to your Sharepoint site with this tool here. If that works you can be sure that the problem is in your code / configuration. That maybe does not solve your problem immediately but it rules out that there is something wrong with the server. Assuming that it does not work I would investigate the following:

  • Does your user really have enough rights on the site?
  • Is there a proxy that interferes? (Your configuration looks a bit like there is a proxy. Can you bypass it?)

I think there is nothing wrong with using security mode Transport, but I am not so sure about the proxyCredentialType="Ntlm", maybe this should be set to None.

感受沵的脚步 2024-09-04 06:39:25

试试这个,

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

我之前在网络农场工作时遇到过这个错误,这为我解决了这个问题。

Try this

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

I've encountered this error before when working in a webfarm and this fixed it for me.

你丑哭了我 2024-09-04 06:39:25

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

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

This issue was even more strange for us. Everything worked if you had previously visited the sharepoint site from the browser, before you made the SOAP call. However, if you did the SOAP call first we'd throw the above error.

We were able to resolve this issue by installing the sharepoint certificate on the client and adding the domain to the local intranet sites.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文