WCF客户端端点:没有<dns>的SecurityNegotiationException如何解决?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (60)

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

有一个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的服务帐户调用。都好。

我现在的问题是:为什么这个工作?这是做什么的?我只通过试验和错误就得到了这个解决方案。对我来说,似乎所有<dns />标记都会告诉客户端使用默认的DNS进行身份验证,但是不是那样做吗? 所以经过一些更多的研究和试错后,我仍然没有找到这个问题的答案。在某些情况下,如果我没有提供<dns />,我会得到Credentials rejected错误,但如果我提供了<dns value="whatever"/>配置,它就会起作用。为什么?

提问于
用户回答回答于

MSDN的“服务身份和身份验证”解释说,端点身份部分支持针对网络钓鱼攻击的客户端安全措施。

来自MSDN:

在客户端启动到端点的通信并且服务向客户端验证自身后,客户端将端点身份值与端点验证过程返回的实际值进行比较。如果它们匹配,则客户确信它已经联系了预期的服务端点。这可以防止客户端被重定向到由恶意服务托管的端点,从而防止网络钓鱼。

另请参阅MSDN的“服务标识示例”

用户回答回答于

<dns/>标签允许客户端验证服务器身份。例如,如果表示<dns value="google.com"/>将验证WCF服务器提供的是google.com身份。既然你说<dns/>这可能只是让大家为你服务。

更多信息在服务身份和身份验证

扫码关注云+社区