WCF 客户端端点:没有 <dns> 的 SecurityNegotiationException

Posted

技术标签:

【中文标题】WCF 客户端端点:没有 <dns> 的 SecurityNegotiationException【英文标题】:WCF client endpoint: SecurityNegotiationException without <dns> 【发布时间】:2011-02-16 10:09:51 【问题描述】:

我在这里遇到了一个奇怪的情况。我得到它的工作,但我不明白为什么。 情况如下:

我的应用程序(网站)必须调用 WCF 服务。 WCF 服务公开 netTcpBinding 并需要传输安全性 (Windows)。 客户端和服务器在同一个域中,但在不同的服务器上。 因此生成客户端会导致以下配置(大部分是默认配置)

<system.serviceModel>
    <bindings>
      <netTcpBinding>
         <binding name="MyTcpEndpoint" ...>          
              <reliableSession ordered="true" inactivityTimeout="00:10:00"
                              enabled="false" />
             <security mode="Transport">
                <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
                <message clientCredentialType="Windows" />
            </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client> 
        <endpoint address="net.tcp://localhost:xxxxx/xxxx/xxx/1.0" 
                   binding="netTcpBinding" bindingConfiguration="MyTcpEndpoint" 
                   contract="Service.IMyService" name="TcpEndpoint"/>
    </client>
</system.serviceModel>

当我运行网站并调用服务时,我收到以下错误:

System.ServiceModel.Security.SecurityNegotiationException: Either the target name is incorrect or the server has rejected the client credentials. ---> System.Security.Authentication.InvalidCredentialException: Either the target name is incorrect or the server has rejected the client credentials. ---> System.ComponentModel.Win32Exception: The logon attempt failed
    --- End of inner exception stack trace ---
    at System.Net.Security.NegoState.EndProcessAuthentication(IAsyncResult result)
    at System.Net.Security.NegotiateStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
    at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.InitiateUpgradeAsyncResult.OnCompleteAuthenticateAsClient(IAsyncResult result)
    at System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorAsyncResult.CompleteAuthenticateAsClient(IAsyncResult result)
    --- End of inner exception stack trace ---

Server stack trace: 
    at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)
    at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
    at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
....

现在,如果我像这样更改客户端的配置:

    <endpoint address="net.tcp://localhost:xxxxx/xxxx/xxx/1.0" 
               binding="netTcpBinding" bindingConfiguration="MyTcpEndpoint" 
               contract="Service.IMyService" name="TcpEndpoint">
        <identity>
            <dns />
        </identity> 
  </endpoint>

一切正常,我的服务器很高兴地报告说它被托管我网站的 AppPool 的服务帐户调用。都很好。

我现在的问题是:为什么会这样?这是做什么的?我只是通过反复试验得到了这个解决方案。在我看来,&lt;dns /&gt; 标签的所有作用似乎就是告诉客户端使用默认 DNS 进行身份验证,但它不这样做吗?

更新 所以经过更多的研究和反复试验,我仍然没有找到这个问题的答案。 在某些情况下,如果我不提供&lt;dns /&gt;,我会收到Credentials rejected 错误,但如果我提供&lt;dns value="whatever"/&gt;config,它会起作用。为什么?

【问题讨论】:

我们的客户端/服务 WCF 通信存在此类 SSPI 问题已经有一段时间了,但始终无法正确解决,并且仅在某些计算机上的某些用户中发生。 “DNS”身份——即使是一个空的身份——似乎也能打勾……哇。 【参考方案1】:

&lt;dns/&gt; 标签允许客户端验证服务器身份。例如,如果您说&lt;dns value="google.com"/&gt;,它将验证 WCF 服务器是否提供了 google.com 身份。既然你说&lt;dns/&gt;,它可能只是让每个人都为你服务。

更多信息Service Identity and Authentication

【讨论】:

嗯,再次阅读该页面后,尝试了一些不同的配置,仍然没有解决。即使我提供 my-crappy-unexisting-dummy-domain.com ,它仍然有效。我想,它必须尝试发出请求,然后回退到默认值,但我在日志中找不到任何暗示 dns 服务器或应用程序服务器甚至试图针对该域进行身份验证的内容......所以我的问题是仍然没有解决。谢谢你帮助我! 我认为您需要一个带有域名的证书才能让客户端进行身份验证。 +1 嗨,你能帮我解释一下吗,那么如果 dns 的值 = "localhost" 是什么意思? @Bhaskar 客户端和服务器必须在同一主机上。【参考方案2】:

MSDN 的"Service Identity and Authentication" 解释说,端点身份部分启用了针对网络钓鱼方案的客户端安全预防措施。

来自 MSDN:

在客户端发起与端点的通信后, 服务向客户端验证自己,客户端比较 端点标识值与端点的实际值 身份验证过程返回。如果它们匹配,客户就放心了 它已经联系了预期的服务端点。 这作为一个 通过防止客户端被网络钓鱼保护 重定向到恶意服务托管的端点。

另请参阅 MSDN 的 "Service Identity Sample"。

【讨论】:

【参考方案3】:

不是答案,但如果您通过代码创建 EndpointAddress,同样的“技巧”会起作用:

// does fail on some machines for some users 
// (I have no explanation here - just crazy)
var address = new EndpointAddress(new Uri(url));

// will work and the dns entry doesn't matter
address = new EndpointAddress(new Uri(url), UpnEndpointIdentity.CreateDnsIdentity(""));

这很奇怪,我不知道为什么会这样,但它似乎有帮助。

【讨论】:

以上是关于WCF 客户端端点:没有 <dns> 的 SecurityNegotiationException的主要内容,如果未能解决你的问题,请参考以下文章

未找到 WCF 命名管道端点

没有端点监听

WCF 多重绑定 - 错误:没有端点监听

WCF - 客户端是不是必须具有与端点相同的行为?

WCF 找不到默认端点

使用WS-MetadataExchange为外部客户端和WcfTestClient公开来自Service Fabric的WCF / TCP端点