20

我浏览了大量的 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”授权。从服务器收到的身份验证标头是“协商,NTLM”。

有人可以帮帮我吗?

4

7 回答 7

10

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

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

我是基于以下几行之间的阅读:选择凭据类型

于 2012-12-04T14:40:38.877 回答
8

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

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

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

我注意到你已经用 xxx.xx.xx.xxx 屏蔽了服务器地址,所以我猜测这是一个 IP 地址而不是服务器名称,这可能会导致身份验证问题,所以如果可能的话尝试定位机器姓名。

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

最后,我会说我遇到过同样的问题,我唯一的办法是使用 Kerberos 而不是 NTLM,别忘了如果你真的走这条路,你需要为该服务注册一个 SPN。

于 2012-12-05T17:57:57.187 回答
6

如果您的客户端和服务都安装在同一台机器上,并且您使用正确的(阅读:在其他地方尝试和测试过)客户端和服务配置面临这个问题,那么这可能值得检查。

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

%windir%/system32/drivers/etc/hosts

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

尝试以下任一方法

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

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

于 2016-03-24T18:13:47.877 回答
4

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

  1. 谈判
  2. NTLM

该应用程序托管了一个 *.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”授权。从服务器收到的身份验证标头是“协商,NTLM”。

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

于 2014-02-17T20:29:47.323 回答
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"
于 2015-03-18T15:50:54.523 回答
1

我知道这个问题很老,但我的应用程序的解决方案与已经建议的答案不同。如果像我这样的其他人仍然有这个问题,并且上述答案都不起作用,这可能是问题:

我使用网络凭据对象将 Windows 用户名+密码解析为第三方 SOAP Web 服务。我设置了用户名=“域名\用户名”、密码=“密码”和域=“域名”。现在这个游戏给我带来了奇怪的 Ntlm 而不是 NTLM 错误。为了解决这些问题,如果域名包含在带有反斜杠的用户名中,请确保不要在 NetworkCredentials 对象上使用 domain 参数。因此,要么从用户名中删除域名并解析域参数,要么省略域参数。这解决了我的问题。

于 2018-12-17T09:28:59.903 回答
0

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

于 2021-06-29T03:15:24.040 回答