我的服务器上有一个启用 WCF 的 Windows 服务,我想使用它。服务器和客户端都应在其存储中具有适当的证书,以便可以使用这些证书来保护通信。
我在 WCF 配置方面不是很有经验,结果证明这是一场噩梦,有很多不同的设置和元素,并不是所有的设置和元素都像我希望的那样记录得很好。
我当前客户端配置的相关部分如下(似乎代码格式在我必须使用的 IE 版本上无法正常工作,希望稍后我会在家修复):
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding">
<security mode="Message">
<message
clientCredentialType="Certificate"
negotiateServiceCredential="false"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="wsHttpCertificateBehavior">
<clientCredentials>
<clientCertificate
findValue="MyCert"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"/>
<serviceCertificate>
<authentication
certificateValidationMode="PeerOrChainTrust"
revocationMode="NoCheck"
trustedStoreLocation="LocalMachine"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint
address="http://someserver:1234/wcf/service/"
behaviorConfiguration="wsHttpCertificateBehavior"
binding="wsHttpBinding"
contract="SomeNamespace.ISomeInterface"
name="wsHttpEndpoint">
<identity>
<servicePrincipalName value="what to put here?"/>
<certificateReference
findValue="MyCert"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
服务器配置是这样的:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
</system.web>
<system.serviceModel>
<services>
<service
name="Os2CentralWcf.CentralAdUserManager"
behaviorConfiguration="wsHttpCertificateBehavior">
<host>
<baseAddresses>
<add baseAddress="http://someserver:1234/wcf/service/"/>
</baseAddresses>
</host>
<endpoint
address=""
binding="wsHttpBinding"
bindingConfiguration="wsHttpEndpointBinding"
contract="SomeNamespace.ISomeInterface"
name="wsHttpEndpoint">
<identity>
<dns value="MyCert"/>
</identity>
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
name="mexEndpoint"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security mode="Message">
<message
establishSecurityContext="false"
negotiateServiceCredential="false"
clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="wsHttpCertificateBehavior">
<serviceMetadata
httpGetEnabled="true"
httpsGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization principalPermissionMode="None"/>
<serviceCredentials>
<clientCertificate>
<authentication
certificateValidationMode="PeerOrChainTrust"
revocationMode="NoCheck"/>
</clientCertificate>
<serviceCertificate
findValue="MyCert"
storeLocation="LocalMachine"
x509FindType="FindBySubjectName"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
在客户端的配置中未指定 aservicePrincipalName
时,我得到以下信息:
System.ServiceModel.Security.MessageSecurityException: Client cannot determine the Service Principal Name based on the identity in the target address 'http://someserver:1234/wcf/service' for the purpose of SspiNegotiation/Kerberos. The target address identity must be a UPN identity (like acmedomain\alice) or SPN identity (like host/bobs-machine).
当尝试添加这样一个元素时(例如<servicePrincipalName value=HOST/someserver:1234"/>
,如下面提到的帖子中所建议的),我最终得到:
System.ServiceModel.Security.SecurityNegotiationException: Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint.
现在我的实际问题是我是否必须使用identity
子元素(错误消息似乎表明了这一点,但我不明白为什么)。我也找不到任何关于在dns
元素中放入什么以及如何指定 servicePrincipalName 的详细文档(如果真的需要——这篇文章也没有真正的帮助)。
在 Visual Studio 2010 中本地运行客户端和服务器(服务)工作正常。我希望我提供了足够的信息,否则请随时询问-不幸的是,如果您开始深入研究 WCF 配置,它似乎会很混乱...
更新
目前使用 basicHttpBinding 能够让双方相互通信,在本地以及在服务器上都可以正常工作。