WCF 服务证书和客户端端点身份 - 为啥它不起作用?
Posted
技术标签:
【中文标题】WCF 服务证书和客户端端点身份 - 为啥它不起作用?【英文标题】:WCF service certificate and client side endpoint identity - why it doesn't work?WCF 服务证书和客户端端点身份 - 为什么它不起作用? 【发布时间】:2010-12-14 15:48:57 【问题描述】:[更新] - 我还附上了完整的配置文件,用于 service 和 client(在此之外,不要淹没主题)
我的情况与this 问题中概述的情况几乎相同,但是我的问题有些不同。
我正在使用具有安全性的 NetTcpBinding 设置为 TransportWithMessageCredential 我正在使用密码/用户名 由 ASP.NET 备份的凭据 提供者 我的服务在 Windows 中自托管 服务 我确实在我的端点行为中 指定认证 revocationMode="NoCheck"服务需要提供证书以向客户端验证自己。没关系,我就是这么做的:
<serviceCertificate findValue="***"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindByThumbprint"/>
现在,我有点想象现在客户最终会拥有
<identity>
<certificate encodedValue="encoded certificate"/>
</identity>
并且它将能够验证服务的凭据无需将该证书安装在客户端计算机上的商店中。
我很惊讶to learn 虽然我将服务凭据设置为证书,但WSDL 暴露了
<Identity>
<Dns>Foo</Dns>
</Identity>
再次,在服务上,我可以将 Identity 设置为 CertificateReference 并将其连接到同一个证书,然后 WSDL 会将身份公开为 X509Certificate,但是当我运行客户端时,该设置被忽略,我最终得到错误消息:
System.ServiceModel.Security.SecurityNegotiationException: X.509 证书 CN=xxx 不在 值得信赖的人商店。 X.509 证书 CN=xxx 建链 失败的。使用的证书 有一条不能被信任的链 已验证。更换证书或 更改证书验证模式。 已处理证书链,但 终止于根证书 不受信任提供者的信任。
有没有办法让客户端使用配置中的值并工作,而无需在客户端机器上安装服务证书(也不是它的根)?
[更新] 虽然将 certificateValidationMode 设置为 none 会使异常消失,但从安全角度来看,这是不可接受的解决方案。
它使客户端仅仅承认它收到了“一些”证书,而不涉及细节。这使得所有范围的中间人攻击成为可能。它仍然不会根据配置中转储的证书验证(所谓的)服务发送的信息。
【问题讨论】:
【参考方案1】:解决方案草图:
1) 在客户端定义并注册一个自定义X509CertificateValidator
2) 在 Validate 方法中,将给定证书与客户端 EndpointAddress.Identity 属性中的证书进行比较。此属性引用的对象应具有 X509CertificateEndpointIdentity 确切类型。
我没有测试这个解决方案,但它对我来说非常有意义。
HTH 佩德罗
【讨论】:
这就是我最终要做的。不过我有一个问题——为什么它不能开箱即用?如果客户端拥有所有必需的信息,并从服务接收到一些证书,那么最自然的做法是验证一个与另一个。为什么 WCF 不这样做? 猜想:出于安全原因。使用建议的解决方案,WSDL 导入过程的安全性变得更加关键,因为在与服务通信时不会执行额外的证书验证。 我刚刚开始对我自己的问题进行赏金,这似乎与您在此处所说的相似。如果您可以在那里更详细地说明解决方案,我将不胜感激! ***.com/questions/4579666/…【参考方案2】:[更新]设置时 certificateValidationMode 为 none 将 让异常消失,它是 安全方面不可接受的解决方案 观点。
它使客户仅仅承认 它收到“一些”证书, 无需详细说明。这 使所有范围的人都在中间 攻击可能。还是不会 验证发送的信息 (据称)服务于 证书转储在配置中。
你错了。这将完美地完成。这实际上就是您想要的 - 您的证书不得到验证。 您只需将客户端上端点的身份设置为
<identity>
<certificate encodedValue="encoded certificate"/>
</identity>
当客户端连接到服务器时,WCF 会比较两个证书,如果不匹配则抛出异常。而且你绝对安全。
在您的情况下,完全没有必要使用建议的 Pedro Felix 之类的自定义验证器。这正是端点身份的用途。
【讨论】:
这具有误导性 - 将 certificateValidationMode 设置为 None 意味着您可以拥有任何 encodeValue 并且不会被检查。【参考方案3】:抱歉,我无法评论其他答案。
我刚刚在 .NET 4.0 中对此进行了测试,我可以确认“Zeratul”的答案是正确的。在配置中或以编程方式显式设置服务的身份足以进行服务器身份验证。无需通过任何其他方式验证证书(即您可以将“certificateValidationMode”设置为“None”),因为您使用的是最终验证方法 - 比较证书的指纹。
@AlexDrenea
“serviceCertificate”不用于验证。它与消息安全性一起用于在消息发送到服务器之前对其进行加密。请参阅 Microsoft 的相关文档:
http://msdn.microsoft.com/en-us/library/ms731782.aspx
【讨论】:
【参考方案4】:这是对我之前回答的补充评论。抱歉,我无法评论答案。
此外,您确实不需要需要在服务器上设置任何身份。忘记 WSDL 告诉您有关服务器身份的内容。远程服务端点的身份由客户端在运行时决定。如果服务器使用 SSL,那么它有几个身份:证书的通用名称(即 DNS 身份)、证书身份和 RSA 身份(不确定最后一个)。因此,您可以通过这些标准中的任何一个(或其中几个)来检查服务器的身份。
【讨论】:
【参考方案5】:您很正确,几乎完成了客户端配置的配置。您缺少最后一件事(如错误描述中所述):您需要在配置中将 revocationMode 设置为 NoCheck:
<behaviors>
<endpointBehaviors>
<behavior name="SecureMessageUserName">
<clientCredentials>
<serviceCertificate>
<authentication revocationMode="NoCheck"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
如果您需要更多详细信息,请告诉我,我会发布完整的有效客户端配置。
编辑抱歉耽搁了
您还应该在服务器配置中添加 noCheck :
<behavior name="X509SecureBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate storeName="My" storeLocation="CurrentUser" x509FindType="FindByThumbprint" findValue="aaaa" />
<clientCertificate>
<authentication certificateValidationMode="None" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
</behavior>
我也没有在端点定义中包含证书引用。
【讨论】:
抱歉,我忘了说我确实设置了这个选项。我相应地更新了问题。无论如何,无论我在这里指定什么,证书似乎都被忽略了。 你能发布一个完整的配置文件吗?还是其中的重要部分? 当然可以,我将它们链接起来,因为它们非常大,而且我不想通过淹没在大量 xml 中来吓跑可能有帮助的人 我不是在抱怨,但这个解决方案对我来说并不适用:( 我不确定我理解你的意思?它不起作用或您由于其他原因无法编辑服务器的配置?以上是关于WCF 服务证书和客户端端点身份 - 为啥它不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
使用 netTcpBinding 为 WCF 服务启用基于证书的身份验证
WCF WS2007FederationHttpBinding 与 HTTPS