过去一周,我一直在为这个爆破的WCF服务的配置而苦苦挣扎,我开始怀疑我正在尝试做的事情是不可能的,尽管有文档。
很简单,我希望WCF服务需要客户端证书(服务器将在其证书存储中具有该证书),然后使用System.ServiceModel.ServiceSecurityContext访问该身份。此外,这需要使用传输安全性。
这是我的服务器配置:
<system.serviceModel>
<services>
<service behaviorConfiguration="requireCertificate" name="Server.CXPClient">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="wsHttpEndpoint" contract="PartnerComm.ContentXpert.Server.ICXPClient" />
<endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="mexEndpoint" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost:8371/Design_Time_Addresses/Server/CXPClient/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="requireCertificate">
<serviceMetadata httpsGetEnabled="true" />
<serviceCredentials>
<serviceCertificate findValue="CyberdyneIndustries" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding" maxBufferPoolSize="5242880" maxReceivedMessageSize="5242880">
<readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="1073741824" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
这是我的客户端配置:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:8371/Design_Time_Addresses/Server/CXPClient/"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" behaviorConfiguration="ClientCertificateBehavior"
contract="ContentXPertServer.ICXPClient" name="wsHttpEndpoint" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<clientCertificate x509FindType="FindBySubjectName" findValue="CyberdyneIndustries" storeLocation="LocalMachine" storeName="TrustedPeople" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
当http的安全模式='无'时,代码全部工作正常,但当然,没有身份验证,System.ServiceModel.ServiceSecurityContext中没有任何内容。我已经尝试了所有这些元素的几十种变体,并且所有这些都不可避免地导致请求抛出异常“现有连接被远程主机强行关闭”。
我正在使用自签名证书“CyberdyneIndustries”,我已将CA证书添加到受信任的CA商店。我查看时证书会检出。我经历了http命名空间管理的地狱,并解决了这些问题。看起来WCF并不真的支持这个...请告诉我我错了。
TIA。
答案 0 :(得分:2)
最终,我决定尝试邮件安全性,看看是否会对情况有所了解 - 它确实如此,我将减少损失并继续使用。所以,对此没有明确的答案。
然而,实现消息安全性确实暴露了一个大问题,这可能是传输安全问题的根源。 MSDN中有一段有毒文档:
http://msdn.microsoft.com/en-us/library/ff650751.aspx
在此页面上,创建自签名证书的命令如下:
makecert -sk MyKeyName -iv RootCaClientTest.pvk -n “CN = tempClientcert”-ic RootCaClientTest.cer -sr currentuser -ss my -sky signature -pe
“签名”这个论点应该是“交换”。一旦我重新生成了所有证书,消息安全就开始工作了。所有这一切的一大亮点是,如果您想要实现传输安全性,请首先使消息安全工作,因为您从系统获得的错误消息更具描述性。
答案 1 :(得分:1)
SSL握手是否成功?启用SChannel日志记录以对SSL层进行故障排除。请参阅这篇旧知识库文章:How to enable Schannel event logging in IIS。虽然是W2K和XP的KB,但启用SChannel日志记录的步骤是相同的,并且在较新的系统上仍然有效。启用日志记录后,您将能够确定SSL拒绝证书的原因。
答案 2 :(得分:1)
我知道这是3岁,但对于那些可能仍感兴趣的人......
我正在学习WCF(其他东西的安全性),并且能够使用netTcpBinding正常工作(可能,这也适用于WsHttpBindings)使用带有clientCredentialType =“Certificate”的传输安全模式(并且,protectionLevel =“EncryptAndSign”,虽然这与该问题没有密切关系)。
我确实遇到了来自服务器端的强制连接关闭错误,但发现我错过了一条配置。现在一切正常。
这是我的服务器端配置:
<configuration>
<system.serviceModel>
<services>
<service name="MyNamespace.MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint address="net.tcp://localhost:9002/MyServer" binding="netTcpBinding" bindingConfiguration="TcpCertSecurity" contract="MyNamespace.IMyService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceCredentials>
<serviceCertificate findValue="MyServiceCert" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="TcpCertSecurity">
<security mode="Transport">
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>
我的客户端配置:
<configuration>
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:9002/MyServer" binding="netTcpBinding"
bindingConfiguration="TcpCertSecurity" contract="MyNamespace.IMyService"
behaviorConfiguration="MyServiceBehavior">
<identity>
<dns value="MyServiceCert" />
</identity>
</endpoint>
</client>
<bindings>
<netTcpBinding>
<binding name="TcpCertSecurity">
<security mode="Transport">
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="MyServiceBehavior">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
<clientCertificate findValue="MyServiceCert" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
我使用描述here的技术为服务器(自签名受信任的根证书+使用该根构建的证书)创建了证书链,并将根证书和子证书存储在我的证书库中服务器主机。最后,我将服务器证书+公钥导入客户端主机上的证书存储区(在LocalMachine / TrustedPeople中)。
答案 3 :(得分:0)
WsHttpBinding DOES支持传输安全性的证书身份验证。
可能有一些问题:
您是否在商店中添加了两个证书? CyberdyneIndustries以及您用来签名的CA? CA应位于“受信任的根证书颁发机构”
此外,我已经完成了这个自托管,从未在Visual Studio Dev服务器中完成。尝试至少在IIS中托管您的服务。我不确定VS Dev服务器是否支持证书。
尝试关闭服务身份验证。因此客户端不必验证服务。我不知道你是否想在你的应用程序中使用它,只是为了测试,所以我们可以排除
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<clientCertificate x509FindType="FindBySubjectName" findValue="CyberdyneIndustries" storeLocation="LocalMachine" storeName="TrustedPeople" />
<serviceCertificate>
<authentication certificateValidationMode="None"/>
</serviceCertificate>
</clientCredentials>