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

问题描述 投票:37回答:5

几天前,在客户端和wcf Web服务之间使用Windows身份验证时,我对身份验证问题非常头疼。我得到的错误是“HTTP请求未经授权,客户端身份验证方案'协商'。从服务器收到的身份验证标头是”NTLM“。堆栈上的解决方案都没有工作,因为大多数解决方案都与旧方法有关。

c# windows wcf authentication
5个回答
25
投票

回答:问题是这个问题的所有帖子都与旧的kerberos和IIS问题有关,其中代理凭证或AllowNTLM属性有帮助。我的情况不同了。我从地面挑选蠕虫数小时后发现的是IIS安装程序列表中的某些IIS安装不包括协商提供程序。所以我不得不添加它并向上移动。我的WCF服务开始按预期进行身份验证。下面是截图,如果您使用匿名身份验证关闭的Windows身份验证,它应该如何。

您需要右键单击Windows身份验证并选择提供程序菜单项。

希望这有助于节省一些时间。


6
投票

我已经将我的旧版本的WCF升级到WCF 4并进行了以下更改,希望您也可以进行类似的更改。

1. Web.config:

<system.serviceModel>
      <bindings>
        <basicHttpBinding>
          <binding name="Demo_BasicHttp">
            <security mode="TransportCredentialOnly">
              <transport clientCredentialType="InheritedFromHost"/>
            </security>
          </binding>
        </basicHttpBinding>
      </bindings>
      <services>
        <service name="DemoServices.CalculatorService.ServiceImplementation.CalculatorService" behaviorConfiguration="Demo_ServiceBehavior">
          <endpoint address="" binding="basicHttpBinding"
              bindingConfiguration="Demo_BasicHttp" contract="DemoServices.CalculatorService.ServiceContracts.ICalculatorServiceContract">
            <identity>
              <dns value="localhost"/>
            </identity>
          </endpoint>
          <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        </service>
      </services>
      <behaviors>
        <serviceBehaviors>
          <behavior name="Demo_ServiceBehavior">
            <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
            <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
            <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
            <serviceDebug includeExceptionDetailInFaults="false"/>
          </behavior>
        </serviceBehaviors>
      </behaviors>
      <protocolMapping>
        <add scheme="http" binding="basicHttpBinding" bindingConfiguration="Demo_BasicHttp"/>
      </protocolMapping>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>

2. App.config:

    <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ICalculatorServiceContract" maxBufferSize="2147483647" maxBufferPoolSize="33554432" maxReceivedMessageSize="2147483647" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="00:10:00">
          <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="4096" />
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Ntlm" proxyCredentialType="None" realm="" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:24357/CalculatorService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICalculatorServiceContract" contract="ICalculatorServiceContract" name="Demo_BasicHttp" />
    </client>
  </system.serviceModel>

4
投票

对我来说,解决方案除了使用“Ntlm”作为凭证类型:

    XxxSoapClient xxxClient = new XxxSoapClient();
    ApplyCredentials(userName, password, xxxClient.ClientCredentials);

    private static void ApplyCredentials(string userName, string password, ClientCredentials clientCredentials)
    {
        clientCredentials.UserName.UserName = userName;
        clientCredentials.UserName.Password = password;
        clientCredentials.Windows.ClientCredential.UserName = userName;
        clientCredentials.Windows.ClientCredential.Password = password;
        clientCredentials.Windows.AllowNtlm = true;
        clientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    }  

0
投票

这不是确切的问题,但这是搜索almost the exact same error时的最佳结果:

如果您在同一台计算机上调用托管WCF服务时遇到此问题,则可能需要填充BackConnectionHostNames注册表项

  1. 在注册表中,找到并单击以下注册表子项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
  2. 右键单击MSV1_0,指向“新建”,然后单击“Multi-String Value”。
  3. 在“名称”列中,键入BackConnectionHostNames,然后按Enter。
  4. 右键单击“BackConnectionHostNames”,然后单击“修改”。在“数值数据”框中,键入用于计算机上本地共享的CNAME或DNS别名,然后单击“确定”。 在单独的行上键入每个主机名。

有关详细信息,请参阅Calling WCF service hosted in IIS on the same machine as client throws authentication error


-1
投票

我的解决方案是将AppPool设置为使用AppPoolIdentity到NetworkService身份。

© www.soinside.com 2019 - 2024. All rights reserved.