WCF异常 - 未提供客户端证书

时间:2013-01-11 10:38:47

标签: wcf ssl certificate self-hosting

WCF异常 - 未提供客户端证书。在ClientCredentials中指定客户端证书。

在阅读了我能够在这个主题上找到的大部分内容,并尝试了许多不同的选项后,我发现我没有更多的头发可以拉,因此这篇文章。

我希望将SSL与自托管WCF服务一起使用,将安全模式作为带有HTTP传输的TransportWithMessageCredential。我正在使用2台开发机器并通过局域网进行测试。

如上所述,我已阅读并仔细地遵循了每一个证明这一点的例子,但不知何故仍然存在证书问题。

就证书而言,我尝试过很多事情。

我所做的主要工作就是遵循所给出的内容 http://msdn.microsoft.com/en-us/library/ff647171.aspx

我还使用了“如何:在Windows窗体中使用WCF调用中的证书身份验证和邮件安全性” http://msdn.microsoft.com/en-us/library/ff648360.aspx 作为基本指南。

我首先在Http上使用basicHttpBinding测试服务和客户端,以验证事情。

然后我对wsHttpBinding,SSL和证书进行了更改。

当我在客户端开发PC上“添加服务引用”时,收到如下错误:

  • 标题窗口 -

安全警报

Visual Studio检测到网站的安全证书存在问题。

发布者:RootCATest 发给:TempCert 证书的有效期为---

公司颁发的安全证书不在不信任列表中。它可能是值得信赖的。

安全证书日期有效。

主机' TempCert'的安全证书。与您尝试查看的页面名称不匹配。

  • 你想继续吗? -

如果单击“是”继续,并运行客户端代码,则会发生InvalidOperationException并显示以下消息。

“未提供客户端证书。在ClientCredentials中指定客户端证书。“

服务配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ServiceBehavior">
                    <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials>
                        <serviceCertificate findValue="CN=TempCert" 
                                            storeLocation="LocalMachine"
                                            storeName="My" />
                    </serviceCredentials>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <bindings>
          <wsHttpBinding>
            <binding name="wsHttpEndpointBinding">
              <security mode="TransportWithMessageCredential">
                <message clientCredentialType="Certificate" />
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>      
        <services>
            <service name="SBSWCFServiceHost.Operations" 
                     behaviorConfiguration="ServiceBehavior">
                <endpoint name="wsHttpEndpoint"
                          address=""
                          binding="wsHttpBinding"
                          bindingConfiguration="wsHttpEndpointBinding"
                          contract="SBSWCFServiceHost.IOperations" >
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>                          
                <endpoint name="mexHttpEndpoint"
                          address="mex"
                          binding="mexHttpsBinding"
                          contract="IMetadataExchange" >
                </endpoint>
                <host>
                    <baseAddresses>
                        <add baseAddress="https://10.0.0.103:8003/SBSWCFServiceHost/Operations/" />
                    </baseAddresses>
                </host>
            </service>
        </services>
    </system.serviceModel>
</configuration>

客户端配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <endpointBehaviors>
                <behavior name="EndpointBehavior">
                    <clientCredentials>
                        <clientCertificate storeLocation="LocalMachine"
                                           storeName="My"
                                           x509FindType="FindByThumbprint"
                                           findValue="e4c87a961f796be6b6cab59c3760e43ffb6e941d"/>
                    </clientCredentials>
              </behavior>
            </endpointBehaviors>
        </behaviors>      
        <bindings>
            <wsHttpBinding>
                <binding name="wsHttpEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00"
                    receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
                    transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Certificate" negotiateServiceCredential="true"
                            algorithmSuite="Default" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
          <endpoint address="https://10.0.0.103:8003/SBSWCFServiceHost/Operations/"
              binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint"
              contract="SBSWCFService.IOperations" name="wsHttpEndpoint">
              <identity>
                  <dns value="localhost" />
              </identity>
          </endpoint>
        </client>
    </system.serviceModel>
</configuration>

以下是我执行的任务摘要,基于众多帖子和文档的内容。

  1. 在服务器上创建自签名CA证书(名为RootCATest),并将其放在本地计算机的“受信任的根证书颁发机构证书”文件夹中。

  2. 在服务器上创建由RootCATest证书(名为TempCert)签名的证书,并将其放在本地计算机的“个人证书”文件夹中。

  3. 导出TempCert证书和私钥。

  4. 将TempCert .cer和.pvk文件复制到客户端计算机,并将TempCert证书导入本地计算机的“个人证书”文件夹。

  5. 执行ICalcs.exe [私钥路径] / grant&#34; NT AUTHORITY \ NETWORK SERVICE&#34;:服务器上的R,使用TempCert证书私钥的路径。

  6. 在服务器计算机上执行netsh http add sslcert ipport = o.o.o.o:8003 certhash = [TempCert thumbprint] appid = [{application id}]

  7. 我相信我已接近完成这项工作。

    很明显应用程序对TempCert证书不满意,但我无法解决这个问题,而且几乎被卡住了。

    对于给定配置中的任何问题的任何帮助,我为遵循正确的证书而采取的步骤,以及用于添加访问权限和sslcert条目的步骤,将不胜感激。

    非常感谢。

    经过一些进一步的实验,我注意到了其他行为。

    采取的措施如下:

    我删除了客户端和服务器证书,并按照重新创建它们 .... codeproject.com/Articles/36683/9-simple-steps-to-enable-x-509-certificates-on-wcf

    我使用netsh添加了新的sslcert。然后我从服务器导出客户端证书 将其导入客户端商店。

    我使用新的证书信息修改了服务app.config,并启动了服务。

    我修改了客户端app.config,如下所示:

    <endpointBehaviors>
      <behavior name="EndpointBehavior">
        <clientCredentials>
          <clientCertificate storeLocation="LocalMachine" storeName="My"  x509FindType="FindBySubjectName" findValue="WCFClient" />
          <serviceCertificate>
            <authentication certificateValidationMode="PeerTrust" />
          </serviceCertificate>
        </clientCredentials>
      </behavior>
    </endpointBehaviors>
    

    我更新了服务参考。更新程序再次发出安全警报。

    然后我执行了客户端,并收到此错误:

    &#34;未提供客户端证书。在ClientCredentials中指定客户端证书。&#34;

    然后我在&#34; client = new WCFService.Client();&#34;上设置断点。并检查了&#34;客户&#34;实例。 client.ClientCredentials.ClientCertificate.Certificate = null。

    的值

    然后我在代码中添加以下内容&#34; client = new WCFService.Client();&#34;:

    X509Store store = new X509Store("My", StoreLocation.LocalMachine);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    X509Certificate2Collection collection = (X509Certificate2Collection) store.Certificates;
    foreach (X509Certificate2 x509 in collection)
    {
    if (x509.Thumbprint == "236D7D4AD95753B8F22D3781D61AACB45518E1B5")
    {
        client.ClientCredentials.ClientCertificate.SetCertificate(
            x509.SubjectName.Name, store.Location, StoreName.My);
    }
    }
    

    执行此代码后,client.ClientCredentials.ClientCertificate.Certificate包含证书。

    然后执行&#34; client.Open();&#34; ,抛出以下内容的异常。

    底层连接已关闭:无法为SSL / TLS安全通道建立信任关系。 根据验证程序,远程证书无效。 无法与具有权限的SSL / TLS安全通道建立信任关系

    如果知道这里可能发生的事情的人可以对此有所了解,我将非常感激。

2 个答案:

答案 0 :(得分:1)

最后一条错误消息表明您的服务器正在从客户端请求客户端证书(服务器必须询问),并且客户端正在提供证书,但服务器无法确定客户端证书是否有效关于服务器机器上可用的信息。

由于您使用的是自签名证书(而不是CA颁发的证书),因此您需要告诉服务器如何验证客户端证书。您可能需要在服务器的My / LocalMachine / Trusted People证书存储中安装客户端证书,以便WCF的默认证书验证可以找到它们,或者在服务器上实现您自己的自定义客户端证书验证程序。 (请参阅WebHttpBinding.Credentials.ClientCertificate.Authentication.CertificateValidationModeWebHttpBinding.Credentials.ClientCertificate.Authentication.CustomCertificateValidator

答案 1 :(得分:0)

我注意到在您的endpoint定义中,您没有引用您定义的behavior。通过一些代码看起来好像在做同等的操作。在配置中加入它可能更简单。

我希望您的端点看起来更像这样:

      <endpoint address="https://10.0.0.103:8003/SBSWCFServiceHost/Operations/"
          binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint"
          contract="SBSWCFService.IOperations" name="wsHttpEndpoint"
          behaviorConfiguration="EndpointBehavior">
          <identity>
              <dns value="localhost" />
          </identity>
      </endpoint>

这是解决方案,当我收到错误“未提供客户端证书时。在ClientCredentials中指定客户端证书”。