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

Posted

技术标签:

【中文标题】HTTP 请求未经客户端身份验证方案“协商”的授权。从服务器收到的身份验证标头是“NTLM”【英文标题】:The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'NTLM' 【发布时间】:2013-03-12 07:05:59 【问题描述】:

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

【问题讨论】:

似乎与我现在遇到的问题相似。能再发一张图吗?谢谢。 你是什么意思“再次发图”,你在帖子中没有看到图像? 对不起,这是一个代理的东西...... postimg.org/image/iriadkxit 这是链接 您应该将自己的答案添加为答案并接受它,以便人们可以投票:)。 【参考方案1】:

答案:问题是所有关于此类问题的帖子都与代理凭据或 AllowNTLM 属性有帮助的旧 kerberos 和 IIS 问题有关。我的情况不同。经过数小时从地下挑选蠕虫后,我发现,在某种程度上,IIS 安装并未在 IIS Windows 身份验证提供程序列表下包含 Negotiate provider。所以我不得不添加它并向上移动。我的 WCF 服务开始按预期进行身份验证。如果您使用 Windows 身份验证并关闭匿名身份验证,以下是屏幕截图。

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

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

【讨论】:

在哪里可以找到这个选项? 在 IIS 中,身份验证不足设置【参考方案2】:

我已将旧版本的 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。应用程序配置:

    <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>

【讨论】:

这在客户端对我有用... 【参考方案3】:

对我来说,解决方案是使用“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;
      

【讨论】:

clientCredentials.Windows.AllowNtlm 已过时【参考方案4】:

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

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

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

详情请见Calling WCF service hosted in IIS on the same machine as client throws authentication error。

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

我有同样的问题,解决它在 iis 中设置域中的特定用户 -> 操作侧边栏 -> 基本设置 -> 连接为... -> 特定用户

【讨论】:

以上是关于HTTP 请求未经客户端身份验证方案“协商”的授权。从服务器收到的身份验证标头是“NTLM”的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 请求未经客户端身份验证方案“基本”授权。从服务器收到的身份验证标头是“协商,NTLM”

HTTP 请求未经客户端身份验证方案“Ntlm”授权

HTTP 请求未经客户端身份验证方案“匿名”授权。使用 wsdl 文件

客户端身份验证方案“匿名”的 HTTP 请求未经授权?

异常 = HTTP 请求未经客户端身份验证方案“匿名”授权

HTTP 请求未经客户端身份验证方案“基本”授权。从服务器收到的身份验证标头为“基本领域 =”