.net HTTP请求未被客户端身份验证方案“Ntlm”授权,从服务器接收的身份验证标头为“协商,NTLM”

xtupzzrd  于 2023-06-25  发布在  .NET
关注(0)|答案(8)|浏览(171)

我已经看了大量的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”。
有人能帮帮我吗?

ldxq2e6h

ldxq2e6h1#

尝试将“clientCredentialType”设置为“Windows”而不是“Ntlm”。
我认为这是服务器所期望的-即。当它说服务器期望“协商,NTLM”时,这实际上意味着Windows Auth,如果Kerberos可用,它将尝试使用Kerberos,如果没有,则返回到NTLM(因此称为“协商”)
我是基于以下几点阅读的:Selecting a Credential Type

smdnsysy

smdnsysy2#

您可以通过使用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
我注意到你已经用www.example.com屏蔽了服务器地址xxx.xx.xx.xxx,所以我猜这是一个IP地址而不是服务器名称,这可能会导致身份验证问题,所以如果可能的话,尝试定位机器名称。
很抱歉,我没有给你答案,但我只是给了你更接近这个问题的指示,但我希望它对你有所帮助。
我最后要说的是,我也遇到过同样的问题,我唯一的办法是使用Kerberos而不是NTLM,不要忘记,如果你真的走这条路,你需要为服务注册SPN。

euoag5mw

euoag5mw3#

如果您的客户端和服务都安装在同一台机器上,并且您正面临此问题,请使用正确(阅读:在其他地方尝试过并测试过)客户端和服务配置,那么这可能值得检查一下。
检查主机文件中的主机条目
%windir%/system32/drivers/etc/hosts
检查您是否正在使用主机名访问Web服务,并且该主机名已与上面提到的hosts文件中的IP地址相关联。如果是,则NTLM/Windows凭据不会从客户端传递到服务,因为对该主机名的任何请求都将在计算机级别再次路由。
请尝试以下操作之一

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

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

ldioqlga

ldioqlga4#

我们遇到了这个问题,并发现当使用浏览器作为进程帐户登录时(在我们的示例中为IE)抛出了错误,然后通过应用程序(SharePoint)更改会话登录。我相信这个场景通过两种身份验证方案:
1.谈判

  1. 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”授权。从服务器收到的身份验证标头为“Negotiate,NTLM”。
最后,我相当肯定,其中一个身份验证方案将通过身份验证,而另一个则不会,因为它没有被授予适当的访问权限。

p8h8hvxi

p8h8hvxi5#

我知道这个问题很老,但我的申请的解决方案与已经建议的答案不同。如果其他人像我一样仍然有这个问题,并且上面的答案都不起作用,这可能是问题所在:
我使用了一个NetworkCredentials对象来解析第三方SOAPWebService的Windows用户名和密码。我设置了username=“domainname\username”,password=“password”和domain=“domainname”。现在这个游戏我奇怪的Ntlm而不是NTLM错误。若要解决此问题,请确保在用户名中包含域名并带有反斜杠时,不要在NetworkCredentials对象上使用domain参数。因此,要么从用户名中删除域名并解析域参数,要么忽略域参数。这解决了我的问题。

wj8zmpe1

wj8zmpe16#

您需要将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"
pes8fvy9

pes8fvy97#

我用的是.NET 5。在我的例子中,我不得不将System.ServiceModel.Http.dll从4.8.1降级到4.4.4。没有太多的时间去挖掘根源。

tzdcorbm

tzdcorbm8#

非常尴尬地承认这一点,但希望能保存别人的痛苦-我使用的是Windows凭据,更改了系统中帐户的密码,并没有更新它的地方,它是从拉。

相关问题