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

时间:2012-12-04 14:05:58

标签: c# .net wcf soap

我查看了大量的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>

但是,从我的控制台应用程序点击它时出现以下错误:

  

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

有人可以帮帮我吗?

7 个答案:

答案 0 :(得分:10)

尝试将'clientCredentialType'设置为'Windows'而不是'Ntlm'。

我认为这就是服务器所期望的 - 即当它说服务器期望“Negotiate,NTLM”时,实际上意味着Windows Auth,它将尝试使用Kerberos(如果可用),或者如果没有则返回NTLM (因此'谈判')

我的基础是:Selecting a Credential Type

答案 1 :(得分:8)

您可以使用wftech从问题中消除客户端,这是一个旧工具,但我发现它在诊断身份验证问题时很有用。 wfetch允许您指定NTLM,Negotiate和kerberos,这可能会帮助您更好地理解您的问题。当您尝试调用服务并且wfetch对WCF一无所知时,我建议将端点绑定(PROVIDERSSoapBinding)应用于serviceMetadata,然后您可以使用相同的安全设置对服务执行WSDL的HTTP GET 。

您可以使用的另一个选项是强制服务器使用NTLM,您可以通过编辑元数据库(IIS 6)并删除协商设置,更多详细信息http://support.microsoft.com/kb/215383来执行此操作。 / p>

如果您使用的是IIS 7.x,则方法略有不同,有关如何配置身份验证提供程序的详细信息位于http://www.iis.net/configreference/system.webserver/security/authentication/windowsauthentication

我注意到您已使用xxx.xx.xx.xxx阻止了服务器地址,因此我猜测这是一个IP地址而不是服务器名称,这可能会导致身份验证问题,所以如果可以尝试定位机器名称。

很抱歉,我没有给你答案,而是提出更接近问题的指示,但我希望它有所帮助。

我说完我也遇到了同样的问题,我唯一的办法就是使用Kerberos而不是NTLM,不要忘记你是否需要为服务注册一个SPN。你沿着这条路走下去。

答案 2 :(得分:4)

我们遇到了这个问题,发现在使用(在我们的情况下是IE)浏览器作为进程帐户登录时,然后通过应用程序(SharePoint)更改会话登录时,会抛出错误。我相信这种情况通过两种身份验证方案:

  1. 协商
  2. NTLM
  3. 应用程序托管了一个* .asmx Web服务,该服务在负载平衡服务器上调用,使用类似WCF的.NET3.5绑定启动对自身的Web服务调用。

    用于调用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();
        }
    }
    

    我们发现,如果会话凭证与浏览器的进程帐户相同,则只使用NTLM并且调用成功。否则会导致捕获到的异常:

      

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

    最后,我相当确定其中一种身份验证方案会通过身份验证,而另一种则不会,因为它未被授予适当的访问权限。

答案 3 :(得分:3)

如果您的客户端和服务都安装在同一台计算机上,并且您在正确(读取:在其他地方尝试过并尝试过)客户端和服务配置时遇到此问题,那么这可能值得一试。

检查主机文件中的主机条目

  

%WINDIR%/ SYSTEM32 /驱动器/ etc / hosts中

检查您是否使用主机名访问Web服务,并且该主机名与上述hosts文件中的IP地址相关联。 如果是,则NTLM / Windows凭证将不会从客户端传递到服务,因为对该主机名的任何请求将在计算机级别再次路由。

尝试以下任一方式

  • 从hosts文件中删除该主机名的主机条目
  • 要么
  • 如果无法删除主机条目,请尝试使用其他主机名访问您的服务。您也可以尝试使用IP地址而不是主机名

编辑: 不知何故,上述情况与负载均衡的情况有关。 但是,如果无法删除主机条目,则禁用机器上的环回检查将有所帮助。 请参阅文章https://support.microsoft.com/en-us/kb/896861

中的方法2

答案 4 :(得分:2)

您需要将NTAuthenticationProviders设置为NTLM

MSDN文章:https://msdn.microsoft.com/en-us/library/ee248703(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"

答案 5 :(得分:1)

我知道这个问题很旧,但是我的应用程序的解决方案与已经提出的答案有所不同。如果像我这样的其他人仍然遇到此问题,但以上答案均无效,则可能是问题所在:

我使用Network Credentials对象将Windows用户名和密码解析为第三方SOAP Web服务。我已经设置了username =“ domainname \ username”,password =“ password”和domain =“ domainname”。现在这个游戏让我觉得奇怪的是Ntlm而不是NTLM错误。 要解决问题,请确保如果域名包含在用户名中并带有反斜杠,则不要在NetworkCredentials对象上使用domain参数。因此,要么从用户名中删除域名,然后在domain参数中进行解析,要么忽略domain参数。这解决了我的问题。

答案 6 :(得分:0)

我使用的是 .NET 5。就我而言,我不得不将 System.ServiceModel.Http.dll 从 4.8.1 降级到 4.4.4。没有太多时间深入挖掘根本原因。

相关问题