【问题标题】:Authenticating to an SSL secured WCF Service from a Winforms client using a self-signed certificate使用自签名证书从 Winforms 客户端对 SSL 安全 WCF 服务进行身份验证
【发布时间】:2014-08-01 13:23:33
【问题描述】:

我正在尝试使用 IIS 生成的自签名证书从 WinForms 客户端连接到 WCF 服务,但无论我做什么,我总是得到“无法为 SSL/TLS 安全通道建立信任关系权威……”。

我的 Web.config 如下所示:

 ...

<binding name="BasicHttpBinding_TransportCertificate">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
</binding>

...

<endpoint address="transportCertificate" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_TransportCertificate"
        name="TransportCertificateEndpoint" contract="MyService"/>

我的客户端代码如下所示:

private void Ping(string endpointAddress)
{
    var binding = new BasicHttpContextBinding();
    binding.Security.Mode = BasicHttpSecurityMode.Transport;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

    var service = new CMServiceReference.CMServiceClient(binding,
        new EndpointAddress(string.Format("{0}/{1}", endpointAddress, "transportCertificate")));

    service.ClientCredentials.ClientCertificate.SetCertificate(
                        StoreLocation.CurrentUser, 
                        StoreName.My,
                        X509FindType.FindBySubjectName, 
                        "server.domain.com");

    service.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;

    service.Ping();
}

设置已安装在客户端计算机上的证书似乎工作得很好,但在调用 service.Ping() 时我仍然总是遇到同样的错误。我玩过 CertificateValidationMode 选项,但似乎没有任何区别。

我有什么明显的遗漏吗?


解决问题后的编辑

事实证明,自签名证书一直在客户端的错误存储中。它需要在本地机器/受信任的根证书颁发机构中。之后,无需在 WCF 属性上指定“证书”即可正常工作。

将证书放在正确的位置后,我只是将我的 Web.config 更新为如下所示:

...

<binding name="BasicHttpBinding_TransportCertificate">
      <security mode="Transport">
        <transport clientCredentialType="None" />
      </security>
</binding>

...

<endpoint address="transportCertificate" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_TransportCertificate"
        name="TransportCertificateEndpoint" contract="MyService"/>

和我的客户代码喜欢这样:

private void Ping(string endpointAddress)
{
    var binding = new BasicHttpContextBinding();
    binding.Security.Mode = BasicHttpSecurityMode.Transport;

    var service = new CMServiceReference.CMServiceClient(binding,
        new EndpointAddress(string.Format("{0}/{1}", endpointAddress, "transportCertificate")));

    service.Ping();
}

【问题讨论】:

  • +1 表示 not 询问如何避免验证。

标签: c# wcf iis ssl


【解决方案1】:

我认为错误是在涉及您的客户端证书之前发生的,即错误是您的客户端应用程序不信任服务器,而不是服务器不信任您的客户端证书。

如果 IIS 证书是自签名的,您需要将该证书作为受信任的根证书安装在本地计算机上。

或者,如果您所做的只是出于测试目的,您可以执行此答案中建议的操作: C# Ignore certificate errors?

这将忽略客户端与服务器之间的任何信任问题。

【讨论】:

  • 这就是答案。证书一直在错误的商店中。它需要在本地机器/受信任的根证书颁发机构中。之后它可以正常工作,而无需在 WCF 属性上指定“证书”。
【解决方案2】:
service.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;

根据MSDN,X509CertificateValidationMode.PeerTrust表示证书在受信任的人存储中有效,但上述函数中的StoreName.My表示从个人证书存储中查找证书,我认为这是原因问题。

如果证书在 StoreName.My 中,您可以删除该行。

【讨论】:

  • 我尝试了你的建议,但仍然遇到同样的错误。
  • 如何获得证书?
  • 在客户端?我现在在证书存储中手动安装它。
  • 哪个证书存储?个人?
  • 目前,是的。通过客户端检索证书不是问题。如果我将 ClientCertificate.SetCertificate() 方法上的 findValue 参数修改为不存在的参数,我会收到不同的错误(“无法使用以下搜索条件找到 X.509 证书:StoreName 'My', StoreLocation 'CurrentUser' , FindType 'FindBySubjectName', FindValue 'server1.domain.com'。")
猜你喜欢
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
  • 1970-01-01
  • 2011-04-09
相关资源
最近更新 更多