使用 X509Certificates 保护 WCF 服务
Using X509Certificates to secure WCF services
我正在处理的场景涉及一个 ASP.NET Web 应用程序与一个使用 netTcpBinding 的自托管 WCF 服务进行通信。这两个组件托管在不同的机器上。 Web服务器是DMZ中的单机,与应用服务器没有信任关系。
我希望在传输级别保护通信。据我了解,如果客户端和应用服务器都安装了合适的X509证书,它们可以相互认证,数据交换也可以加密。
我已经为 Web 服务器提供了 ClientAuthentication 证书,并为应用程序服务器提供了 ServerAuthentication 证书。在每种情况下,证书都存储在 LocalMachine\My 存储中。我已确保私钥可用于所有证书,并且应用程序池身份和 BUILTIN\LOCAL 身份(分别在 Web 和应用程序服务器上)具有对私钥的完全访问权限。我还将证书的 public 关键部分(即 .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'. ---&gt; System.IO.IOException: The read operation failed, see inner exception. ---&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'. ---&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 ---
任何人都可以建议我需要对这个配置做些什么才能让它工作吗?
我相信你错过了:
服务器端
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" />
</clientCertificate>
</serviceCredentials>
客户端
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
我正在处理的场景涉及一个 ASP.NET Web 应用程序与一个使用 netTcpBinding 的自托管 WCF 服务进行通信。这两个组件托管在不同的机器上。 Web服务器是DMZ中的单机,与应用服务器没有信任关系。
我希望在传输级别保护通信。据我了解,如果客户端和应用服务器都安装了合适的X509证书,它们可以相互认证,数据交换也可以加密。
我已经为 Web 服务器提供了 ClientAuthentication 证书,并为应用程序服务器提供了 ServerAuthentication 证书。在每种情况下,证书都存储在 LocalMachine\My 存储中。我已确保私钥可用于所有证书,并且应用程序池身份和 BUILTIN\LOCAL 身份(分别在 Web 和应用程序服务器上)具有对私钥的完全访问权限。我还将证书的 public 关键部分(即 .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'. ---&gt; System.IO.IOException: The read operation failed, see inner exception. ---&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'. ---&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 ---
任何人都可以建议我需要对这个配置做些什么才能让它工作吗?
我相信你错过了:
服务器端
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" />
</clientCertificate>
</serviceCredentials>
客户端
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>