WCF服务证书和客户端端点身份 - 为什么它不起作用?

时间:2009-11-09 14:43:23

标签: wcf security certificate

[更新] - 我还为serviceclient附加了完整的配置文件(在此处之外,不要充斥主题)

我的情况与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。   已处理证书链,但是   终止于根证书中   信任提供商不信任。

有没有办法让客户端从配置和工作中使用该值而无需在客户端的计算机上安装服务证书(也不是它的根目录)?

[UPDATE] 将certificateValidationMode设置为none会使异常消失,从安全角度来看,这是不可接受的解决方案。

它使客户只是承认它收到“某些”证书,而没有详细说明。这使得所有中间人攻击都成为可能。它仍然不会验证(涉嫌)服务针对配置中转储的证书发送的信息。

5 个答案:

答案 0 :(得分:4)

解决方案草图:

1)在客户端上定义并注册自定义 X509CertificateValidator

2)在验证方法中,将给定证书与客户端的 EndpointAddress.Identity 属性中存在的证书进行比较。此属性引用的对象应具有 X509CertificateEndpointIdentity 精确类型。

我没有测试过这个解决方案,但这对我来说非常合理。

HTH 佩德罗

答案 1 :(得分:2)

  

[更新]设置时   certificateValidationMode为none   让例外消失,它是   来自安全的不可接受的解决方案   观点。

     

它使客户只是承认   它收到“一些”证书,   没有详细说明。这个   让所有男人都处于中间位置   攻击可能。它仍然不会   验证发送的信息   (据称)服务反对   证书转储在配置中。

你错了。这将完美。这实际上就是你想要的 - 你的证书得到验证。 您所需要的只是将客户端上的端点标识设置为

<identity>
  <certificate encodedValue="encoded certificate"/>
</identity>

当客户端连接到服务器时,WCF将比较两个证书并在它们不匹配时抛出异常。你是完全安全的。

在您的情况下,使用像 Pedro Felix 这样的自定义验证程序是完全没有必要的。这正是端点身份的用途。

答案 2 :(得分:2)

对不起,我无法评论其他答案。

我刚刚在.NET 4.0中对此进行了测试,我可以确认“Zeratul”的答案是正确的。在配置中明确设置服务的标识,或者以编程方式明确设置服务器身份验证。无需通过任何其他方式验证证书(即您可以将“certificateValidationMode”设置为“None”),因为您使用的是最终验证方法 - 比较证书的指纹。

@AlexDrenea

“serviceCertificate”不用于验证。它与消息安全性一起用于在将消息发送到服务器之前对其进行加密。请参阅Microsoft的文档:

http://msdn.microsoft.com/en-us/library/ms731782.aspx

答案 3 :(得分:1)

这是对我之前回答的补充评论。对不起,我无法评论答案。

此外,您需要在服务器上设置任何身份。忘记WSDL告诉你的服务器身份。远程服务端点的标识由客户端在运行时决定。如果服务器使用SSL,则它具有多个身份:证书的通用名称(即DNS身份),证书身份和RSA身份(不确定最后一个)。因此,您可以按照这些标准中的任何一个(或其中几个标准)检查服务器的身份。

答案 4 :(得分:0)

您是核心,几乎已完成配置客户端配置。你遗漏了最后一件事(如错误描述中所述):你需要在配置中将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>

此外,我没有在端点定义中包含证书引用。