【发布时间】:2012-10-23 21:14:30
【问题描述】:
我正在开发一个基于供应商实现的 WCF 服务,以从他们那里接收数据。我有一个使用单向 SSL 的服务的工作版本,客户端使用我们的服务器证书。由于最近对他们的实现进行了更改,我现在需要使用证书而不是用户名和密码来验证他们的客户端。
他们使用 Java 开发,我无法控制客户端或他们生成证书的方式。它们不支持 WSHttpBinding,所以我必须使用 BasicHttpBinding。他们的证书是自签名的,很遗憾在生产中也是如此。我尝试使用 Transport 来保证安全性,根据我们的服务器管理员的说法,他们的证书已正确安装在我们的服务器上(我无权访问我们的 IIS 服务器)。我认为 IIS 的证书存在问题,因为它是自签名的,所以我放弃了该实现。
经过大量研究后,我确定它可能只有在我通过从OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets[0] 获取服务本身中验证他们的证书时才有效。这是我的第一个 WCF 服务,所以我相信我已经正确设置了它,但是从我的 WCF 测试客户端进行测试时出现以下错误:The private key is not present in the X.509 certificate。当我从他们的客户那里得到供应商测试时,他们得到了An error occurred when verifying security for the message.
我是否有错误配置?是否支持此实现?
服务 Web.Config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="FileReceiverServiceBehavior">
<useRequestHeadersForMetadataAddress/>
<serviceMetadata httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="FileReceiverServiceBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Certificate"/>
</security>
<readerQuotas maxStringContentLength="2147483647"/>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="FileReceiverServiceBehavior" name="FileReceiverService.FileReceiverService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="FileReceiverServiceBinding" contract="FileReceiverServiceSoap" bindingNamespace="http://www.openuri.org/" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
</configuration>
我的 WCF 测试客户端配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="test">
<clientCredentials>
<clientCertificate findValue="Users"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_FileReceiverServiceSoap" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://mydomain.com/vendor/FileReceiverService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_FileReceiverServiceSoap"
contract="ServiceReference1.FileReceiverServiceSoap" name="BasicHttpBinding_FileReceiverServiceSoap" behaviorConfiguration="test" />
</client>
</system.serviceModel>
</configuration>
更新:
供应商向我发送了正确的证书。它是由商业 CA 颁发的有效证书。当我在本地查看证书时,我可以看到到受信任根的链,并且状态显示为“OK”。
如果我使用 security mode="Transport" 和 transport clientCredentialType="Certificate" 我得到:HTTP 请求被客户端身份验证方案“匿名”禁止
如果我使用 security mode="TransportWithMessageCredential" 和 message clientCredentialType="Certificate" 我得到:X.509 证书中不存在私钥。
我认为我可能需要严格使用传输,以便它可以与 Java 客户端互操作,因此我将重点关注“客户端身份验证方案‘匿名’禁止 HTTP 请求”错误。这是 IIS 设置的问题,还是只是在证书到达服务器时无法正确验证证书?证书在受信任的人中,我没有尝试过客户端certificateValidationMode,但也尝试了PeerTrust、ChainTrust 和PeerOrChainTrust。任何帮助将不胜感激。
更新2:
我的重点是让它与对我的原始服务器配置的以下更改以及对我的测试客户端的匹配更改一起工作:
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
我仍然得到:HTTP 请求被客户端身份验证方案“匿名”禁止。我找到了一个解释here,基本上可以确认客户端证书无法被服务器验证。我如何让我们的服务器管理员在 IIS 中配置此应用程序并安装证书以使其正常工作?
【问题讨论】:
-
我猜您只需要在 IIS 服务器上的受信任存储中安装客户端证书即可。由于它是自签名证书,您可能会遇到 IIS 抛出的异常,它无法验证证书。您可以在不验证客户端证书的链信任的 serviceBehaviour 中尝试以下设置:
-
@Rajesh 谢谢你的回复。我尝试使用安全模式 = 传输和传输 clientCredentialType = 证书设置并收到以下错误:“HTTP 请求被客户端身份验证方案‘匿名’禁止。”这是我在没有您建议的设置更改的情况下使用该设置收到的错误。我可能有一个解决方案。供应商可能给我发错了证书。我正在使用“正确”证书进行测试,看看它是否有效。
-
@Rajesh 我在使用正确的证书时遇到了同样的错误。有关完整信息,请参阅我的更新。
-
@user1769388 我看不到您在 web.config 中添加自定义验证的位置(您在顶部提到了这一点)。 Check out MSDN on custom cert validation
-
@user1769388 此外,私钥不存在错误可能表明“算法套件”的选择存在问题。尝试在两侧专门设置它,某些证书不支持所有不同的套件。我必须先将我的设置为 DES,然后从那里向上移动。测试这一点的一个好方法是在证书上设置一个 pin(或密码),它应该在访问签名时(通过客户端)提示您,如果没有,则该证书不支持您的签名算法。跨度>
标签: c# wcf ssl authentication java-client