使用自签名证书从Winforms客户端验证SSL安全WCF服务

时间:2014-08-01 13:23:33

标签: c# wcf iis ssl

我尝试使用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选项,但这些选项似乎都没有任何区别。

我有什么明显的遗失吗?


解决问题后的编辑

事实证明,自签名证书一直存在于客户端的错误存储中。它需要位于本地计算机/受信任的根证书颁发机构中。之后它没有&#34;证书&#34;在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();
}

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

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

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

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

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