C# HTTP 请求未经客户端身份验证方案“Ntlm”授权。从服务器收到的身份验证标头是“协商,NTLM”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13704720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'Negotiate,NTLM'
提问by Mike Perrenoud
I've looked through a ton of SO articles, and even other sites, but can't seem to get this service working. I have a SOAP service I'm trying to hit and it's configured like this:
我浏览了大量 SO 文章,甚至其他网站,但似乎无法使此服务正常工作。我有一个 SOAP 服务,我正在尝试使用它,它的配置如下:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="PROVIDERSSoapBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xxx.xx.xx.xxx:9011/provider/services/PROVIDERS"
binding="basicHttpBinding" bindingConfiguration="PROVIDERSSoapBinding"
contract="ServiceReference1.ProviderRemote" name="PROVIDERS" />
</client>
</system.serviceModel>
However, I'm getting the following error when hitting it from my console application:
但是,从我的控制台应用程序点击它时出现以下错误:
The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'Negotiate,NTLM'.
HTTP 请求未经客户端身份验证方案“Ntlm”授权。从服务器收到的身份验证标头是“协商,NTLM”。
Can somebody help me out?
有人可以帮我吗?
采纳答案by David Martin
You can eliminate the client from the problem by using wftech, this is an old tool but I have found it useful in diagnosing authentication issues. wfetch allows you to specify NTLM, Negotiate and kerberos, this may well help you better understand your problem. As you are trying to call a service and wfetch knows nothing about WCF, I would suggest applying your endpoint binding (PROVIDERSSoapBinding) to the serviceMetadatathen you can do an HTTP GET of the WSDL for the service with the same security settings.
您可以使用wftech消除客户端的问题,这是一个旧工具,但我发现它在诊断身份验证问题时很有用。wfetch 允许您指定 NTLM、Negotiate 和 kerberos,这可能有助于您更好地了解您的问题。当您尝试调用服务而 wfetch 对 WCF 一无所知时,我建议将您的端点绑定 (PROVIDERSSoapBinding) 应用到serviceMetadata,然后您可以使用相同的安全设置为服务执行 WSDL 的 HTTP GET。
Another option, which may be available to you is to force the server to use NTLM, you can do this by either editing the metabase (IIS 6) and removing the Negotiate setting, more details at http://support.microsoft.com/kb/215383.
您可能可以使用的另一个选项是强制服务器使用 NTLM,您可以通过编辑元数据库 (IIS 6) 并删除协商设置来执行此操作,更多详细信息请访问http://support.microsoft.com/知识库/215383。
If you are using IIS 7.x then the approach is slightly different, details of how to configure the authentication providers are here http://www.iis.net/configreference/system.webserver/security/authentication/windowsauthentication.
如果您使用的是 IIS 7.x,则方法略有不同,有关如何配置身份验证提供程序的详细信息,请访问 http://www.iis.net/configreference/system.webserver/security/authentication/windowsauthentication。
I notice that you have blocked out the server address with xxx.xx.xx.xxx, so I'm guessing that this is an IP address rather than a server name, this may cause issues with authentication, so if possible try targeting the machine name.
我注意到你已经用 xxx.xx.xx.xxx 屏蔽了服务器地址,所以我猜这是一个 IP 地址而不是服务器名称,这可能会导致身份验证问题,所以如果可能的话尝试定位机器姓名。
Sorry that I haven't given you the answer but rather pointers for getting closer to the issue, but I hope it helps.
抱歉,我没有给您答案,而是提供了更接近问题的指示,但我希望它有所帮助。
I'll finish by saying that I have experienced this same issue and my only recourse was to use Kerberos rather than NTLM, don't forget you'll need to register an SPN for the service if you do go down this route.
最后,我要说我遇到了同样的问题,我唯一的办法是使用 Kerberos 而不是 NTLM,不要忘记,如果你真的沿着这条路线走,你需要为该服务注册一个 SPN。
回答by Chamila Chulatunga
Try setting 'clientCredentialType' to 'Windows' instead of 'Ntlm'.
尝试将“clientCredentialType”设置为“Windows”而不是“Ntlm”。
I think that this is what the server is expecting - i.e. when it says the server expects "Negotiate,NTLM", that actually means Windows Auth, where it will try to use Kerberos if available, or fall back to NTLM if not (hence the 'negotiate')
我认为这是服务器所期望的 - 即当它说服务器期望“协商,NTLM”时,这实际上意味着 Windows 身份验证,如果可用,它将尝试使用 Kerberos,或者如果没有,则回退到 NTLM(因此'谈判')
I'm basing this on somewhat reading between the lines of: Selecting a Credential Type
我基于以下几行之间的一些阅读:选择凭据类型
回答by ISZ
We encountered this issue and discovered that the error was being thrown when using (IE in our case) the browser logged in as the process account, then changing the session log in through the application (SharePoint). I believe this scenario passes two authentication schemes:
我们遇到了这个问题,并发现在使用(在我们的例子中是 IE)浏览器作为进程帐户登录,然后通过应用程序(SharePoint)更改会话登录时抛出错误。我相信这个场景通过了两种身份验证方案:
- Negotiate
- NTLM
- 谈判
- NTLM
The application hosted an *.asmx web service, that was being called on a load balanced server, initiating a web service call to itself using a WCF-like .NET3.5 binding.
该应用程序托管了一个 *.asmx Web 服务,该服务在负载平衡服务器上被调用,使用类似 WCF 的 .NET3.5 绑定启动对自身的 Web 服务调用。
Code that was used to call the web service:
用于调用 Web 服务的代码:
public class WebServiceClient<T> : IDisposable
{
private readonly T _channel;
private readonly IClientChannel _clientChannel;
public WebServiceClient(string url)
: this(url, null)
{
}
/// <summary>
/// Use action to change some of the connection properties before creating the channel
/// </summary>
public WebServiceClient(string url,
Action<CustomBinding, HttpTransportBindingElement, EndpointAddress, ChannelFactory> init)
{
var binding = new CustomBinding();
binding.Elements.Add(
new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8));
var transport = url.StartsWith("https", StringComparison.InvariantCultureIgnoreCase)
? new HttpsTransportBindingElement()
: new HttpTransportBindingElement();
transport.AuthenticationScheme = System.Net.AuthenticationSchemes.Ntlm;
binding.Elements.Add(transport);
var address = new EndpointAddress(url);
var factory = new ChannelFactory<T>(binding, address);
factory.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
if (init != null)
{
init(binding, transport, address, factory);
}
this._clientChannel = (IClientChannel)factory.CreateChannel();
this._channel = (T)this._clientChannel;
}
/// <summary>
/// Use this property to call service methods
/// </summary>
public T Channel
{
get { return this._channel; }
}
/// <summary>
/// Use this porperty when working with
/// Session or Cookies
/// </summary>
public IClientChannel ClientChannel
{
get { return this._clientChannel; }
}
public void Dispose()
{
this._clientChannel.Dispose();
}
}
We discovered that if the session credential was the same as the browser's process account, then just NTLM was used and the call was successful. Otherwise it would result in this captured exception:
我们发现,如果会话凭证与浏览器的进程帐户相同,则只使用了 NTLM 并且调用成功。否则会导致这个捕获的异常:
The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'Negotiate,NTLM'.
HTTP 请求未经客户端身份验证方案“Ntlm”授权。从服务器收到的身份验证标头是“协商,NTLM”。
In the end, I am fairly certain that one of the authentication schemes would pass authentication while the other wouldn't, because it was not granted appropriate access.
最后,我相当确定其中一个身份验证方案会通过身份验证,而另一个则不会,因为它没有被授予适当的访问权限。
回答by mistrykam
You need to set the NTAuthenticationProviders to NTLM
您需要将 NTAuthenticationProviders 设置为 NTLM
MSDN Article: https://msdn.microsoft.com/en-us/library/ee248703(VS.90).aspx
MSDN 文章:https: //msdn.microsoft.com/en-us/library/ee248703(VS.90).aspx
IIS Command-line (http://msdn.microsoft.com/en-us/library/ms525006(v=vs.90).aspx):
IIS 命令行 ( http://msdn.microsoft.com/en-us/library/ms525006(v=vs.90).aspx):
cscript adsutil.vbs set w3svc/WebSiteValueData/root/NTAuthenticationProviders "NTLM"
回答by ash
If both your client and service is installed on the same machine, and you are facing this problem with the correct (read: tried and tested elsewhere) client and service configurations, then this might be worth checking.
如果您的客户端和服务都安装在同一台机器上,并且您遇到了正确(阅读:在其他地方尝试和测试过)客户端和服务配置的问题,那么这可能值得检查。
Check host entries in your host file
检查主机文件中的主机条目
%windir%/system32/drivers/etc/hosts
%windir%/system32/drivers/etc/hosts
Check to see if you are accessing your web service with a hostname, and that same hostname has been associated with an IP address in the hosts file mentioned above. If yes, NTLM/Windows credentials will NOT be passed from the client to the service as any request for that hostname will be routed again at the machine level.
检查您是否正在使用主机名访问 Web 服务,并且该主机名是否已与上述主机文件中的 IP 地址相关联。如果是,NTLM/Windows 凭据将不会从客户端传递到服务,因为对该主机名的任何请求都将在机器级别再次路由。
Try either of the following
尝试以下任一方法
- Remove the host entry of that hostname from the hosts file OR
- If removing host entry is not possible, then try accessing your service with another hostname. You might also try with IP address instead of hostname
- 从主机文件中删除该主机名的主机条目 或者
- 如果无法删除主机条目,请尝试使用其他主机名访问您的服务。您也可以尝试使用 IP 地址而不是主机名
Edit: Somehow the above situation is relevant on a load-balanced scenario. However, if removing the host entries is not possible, then disabling loop back check on the machine will help. Refer method 2 in the article https://support.microsoft.com/en-us/kb/896861
编辑:不知何故,上述情况与负载平衡方案相关。但是,如果无法删除主机条目,则禁用机器上的环回检查会有所帮助。参考文章https://support.microsoft.com/en-us/kb/896861中的方法 2
回答by nivs1978
I know this question is old, but the solution to my application, was different to the already suggested answers. If anyone else like me still have this issue, and none of the above answers works, this might be the problem:
我知道这个问题很旧,但是我的应用程序的解决方案与已经建议的答案不同。如果像我这样的其他人仍然有这个问题,并且上述答案都不起作用,这可能是问题所在:
I used a Network Credentials object to parse a windows username+password to a third party SOAP webservice. I had set the username="domainname\username", password="password" and domain="domainname". Now this game me that strange Ntlm and not NTLM error. To solve the problems, make sure not to use the domain parameter on the NetworkCredentials object if the domain name is included in the username with the backslash. So either remove domain name from the username and parse in domain parameter, or leave out the domain parameter. This solved my issue.
我使用网络凭据对象将 Windows 用户名+密码解析为第三方 SOAP 网络服务。我已经设置了 username="domainname\username"、password="password" 和 domain="domainname"。现在这个游戏让我觉得奇怪的 Ntlm 而不是 NTLM 错误。为了解决这些问题,如果域名包含在带有反斜杠的用户名中,请确保不要在 NetworkCredentials 对象上使用 domain 参数。因此,要么从用户名中删除域名并解析域参数,要么省略域参数。这解决了我的问题。

