1

我正在处理的场景涉及一个 ASP.NET Web 应用程序,它与一个使用 netTcpBinding 的自托管 WCF 服务进行通信。这两个组件托管在不同的机器上。Web 服务器是 DMZ 中的独立机器,与应用程序服务器没有信任关系。

我希望在传输级别上确保通信安全。据我了解,如果客户端和应用服务器都安装了合适的 X509 证书,它们可以相互验证,并且数据交换也可以加密。

我已经为 Web 服务器提供了 ClientAuthentication 证书,并为应用服务器提供了 ServerAuthentication 证书。在每种情况下,证书都存储在 LocalMachine\My 存储中。我已确保私钥可用于所有证书,并且应用程序池身份和 BUILTIN\LOCAL 身份(分别在 Web 和应用服务器上)具有对私钥的完全访问权限。我还将证书的公钥部分(即 .cer 文件)复制到了对面服务器上的 LocalMachine\TrustedPeople 存储中。

配置如下所示:

应用服务器

<services>
  <service behaviorConfiguration="DefaultServiceBehavior" name="Evs.Application.Services.XXXXXProvider">
    <endpoint address="net.tcp://localhost:8000/Evs.Application.Services/XXXXXServiceCert"
              binding="netTcpBinding" bindingConfiguration="SecureCertificateNetTcpBinding" contract="Evs.Application.Contracts.IXXXXXProvider"
              behaviorConfiguration="endpointBehavior"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="DefaultServiceBehavior">
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceCredentials>
        <serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" findValue="xxxxxxxxxxxxxx"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>
<bindings>
    <binding name="SecureNetTcpBinding">
      <security mode="Transport" />
    </binding>
    <binding name="SecureCertificateNetTcpBinding">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </netTcpBinding>
</bindings>

网络服务器

<client>
  <endpoint address="net.tcp://app-ext-01.prod.mydomain.com:8000/Evs.Application.Services/XXXXXServiceCert"
            behaviorConfiguration="secureEndPointBehaviour" binding="netTcpBinding"
            bindingConfiguration="SecureCertificateNetTcpBinding" contract="Evs.Application.Contracts.IXXXXXProvider"
            name="XXXXXProvider"/>
<client>
<behaviors>
  <endpointBehaviors>
    <behavior name="secureEndPointBehaviour">
      <clientCredentials>
        <clientCertificate findValue= "xxxxxxxxxxxxxxxxxxx"
         storeLocation="LocalMachine" storeName="My"
         x509FindType="FindByThumbprint"/>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>
<bindings>
  <netTcpBinding>
    <binding name="SecureCertificateNetTcpBinding">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </netTcpBinding>
</bindings>

在我用于测试的登台环境中,对服务的调用失败,但出现以下异常(从服务器端日志中检索)

System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:59.9840000'. ---&amp;gt; System.IO.IOException: The read operation failed, see inner exception. ---&amp;gt; 
System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:59.9840000'. ---&amp;gt; System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
   --- End of inner exception stack trace ---
   at System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
   at System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   at System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   --- End of inner exception stack trace ---
   at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   --- End of inner exception stack trace ---

谁能建议我需要对此配置做些什么才能使其正常工作?

4

1 回答 1

2

我相信你错过了:

服务器端

<serviceCredentials>
  <clientCertificate>
    <authentication certificateValidationMode="PeerTrust" />
  </clientCertificate>
</serviceCredentials>

客户端

<clientCredentials>
  <serviceCertificate>
    <authentication certificateValidationMode="PeerTrust" />
  </serviceCertificate>
</clientCredentials>
于 2015-03-12T18:19:53.050 回答