WCF 上的 X.509 证书?

Posted

技术标签:

【中文标题】WCF 上的 X.509 证书?【英文标题】:X.509 certificates on WCF? 【发布时间】:2012-07-14 00:29:50 【问题描述】:

问题:

我正在一台机器上开发这个程序。

该服务在开发服务器中运行良好,但是当我尝试在 IIS 中托管该服务时,它给了我一个错误:

使用以下搜索条件找不到 X.509 证书:StoreName 'My'、StoreLocation 'CurrentUser'、FindType 'FindBySubjectName'、FindValue 'WCFServer'。

那么有没有办法解决这个问题? 我正在尝试从

http://www.codeproject.com/KB/WCF/9StepsWCF.aspx

证书创建

makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=WCfServer -sky exchange -pe
makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=WcfClient -sky exchange -pe

证书存在于 MMC 的个人和受信任的人文件夹中

服务有一个函数,它接受一个数字并返回字符串并且工作正常

这是我的服务 web.config:

<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpEndpointBinding">
          <security>
            <message clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="WCFServiceCertificate.Service1" behaviorConfiguration="WCFServiceCertificate.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" contract="WCFServiceCertificate.IService1">
          <!--
              Upon deployment, the following identity element should be removed or replaced to reflect the
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity
              automatically.
          -->
          <!--<identity>
            <dns value="localhost"/>
          </identity>-->
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCFServiceCertificate.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerTrust"/>
            </clientCertificate>
            <serviceCertificate findValue="WcfServer"
                                storeLocation="CurrentUser"
                                storeName="My"
                                x509FindType="FindBySubjectName" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

这是我的客户端配置

<system.serviceModel>
                <bindings>
   <wsHttpBinding>
    <binding name="WSHttpBinding_IService1" 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="Message">
      <transport clientCredentialType="Windows" proxyCredentialType="None"
       realm="" />
      <message clientCredentialType="Certificate" negotiateServiceCredential="true"
       algorithmSuite="Default" establishSecurityContext="true" />
     </security>
    </binding>
   </wsHttpBinding>
  </bindings>
                <client>
   <endpoint address="http://localhost:1387/Service1.svc" behaviorConfiguration="CustomBehavior"
    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
    contract="ServiceReference1.IService1" name="WSHttpBinding_IService1">
    <identity>
     <certificate encodedValue="AwAAAAEAAAAUAAAA9YoGKvsMLFkeO1WjaCLReQuz1ysgAAAAAQAAALUBAAAwggGxMIIBX6ADAgECAhDDvb3bnmzhsERpNTWEBYQXMAkGBSsOAwIdBQAwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3kwHhcNMTEwMzA0MDcwNzU3WhcNMzkxMjMxMjM1OTU5WjAUMRIwEAYDVQQDEwlXY2ZTZXJ2ZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM9e4DwCDYJ4l6myt1QadHzXoqCH2wa1aUjiab1aK/7d/1LZ00KfPJw8kKB358serjEi9SMg0UeyGtl0+byJ8PqShfv4MUTHZcPaWy99vHaYHwH7T9hVwY5RANBWyFy6nf1rXDh/cB2qm0Q/xN5xElOtheFqUoL8Ua6fcP33BAWPAgMBAAGjSzBJMEcGA1UdAQRAMD6AEBLkCS0GHR1PAI1hIdwWZGOhGDAWMRQwEgYDVQQDEwtSb290IEFnZW5jeYIQBjdsAKoAZIoRz7jUqlw19DAJBgUrDgMCHQUAA0EAKlaHJQNdC9VgPuHlVuniQJd+fHoVOU62nl374iXYdQus5KDgKz9RHWAtjhpToBB4sOXOnwTkJfcyJWBf6J14Mw==" />
    </identity>
   </endpoint>
  </client>
                <behaviors>
                        <endpointBehaviors>
                                <behavior name="CustomBehavior">
                                        <clientCredentials>
                                                <clientCertificate findValue="WcfClient"
                               x509FindType="FindBySubjectName"
                               storeLocation="CurrentUser"
                               storeName="My"/>
                                                <serviceCertificate>
                                                        <authentication certificateValidationMode="PeerTrust"/>
                                                </serviceCertificate>
                                        </clientCredentials>
                                </behavior>
                        </endpointBehaviors>
                </behaviors>
        </system.serviceModel>

并简单地使用这个在客户端调用服务

 Service1Client obj = new Service1Client();
            Response.Write(obj.GetData(12));

现在,当我运行时,一切正常,没有问题。

您可以在开发服务器上运行服务。

但是当我尝试在 IIS 中托管服务时,它给了我一个错误

使用以下搜索条件找不到 X.509 证书: StoreName '我的',StoreLocation 'CurrentUser',FindType 'FindBySubjectName',FindValue 'WCFServer'。

那我有办法解决这个问题吗?

【问题讨论】:

【参考方案1】:

正如x0n 提到的,Cassini 将以您当前的用户身份运行,但 IIS 将以 IUSR 身份运行。将带有私钥的证书导入 LocalMachine\Personal (LocalMachine\My),然后更改您的服务配置:

        <serviceCertificate findValue="WcfServer"
                            storeLocation="CurrentUser"
                            storeName="My"
                            x509FindType="FindBySubjectName" />

到这里:

        <serviceCertificate findValue="WcfServer"
                            storeLocation="LocalMachine"
                            storeName="My"
                            x509FindType="FindBySubjectName" />

【讨论】:

【参考方案2】:

您可能需要在客户端>endpoint >indentity 中设置 dns 值,即证书的名称(如下面的代码所述)

<client>
        <endpoint address="http://localhost/FrontPMWebServiceSetup111/FpmService.svc"
          binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService"
          contract="FPMServiceReference.IService" name="WSHttpBinding_IService">
          <identity>
            <dns value="WCfServer" />
          </identity>
        </endpoint>
      </client>

【讨论】:

【参考方案3】:

在计算机商店的“我的”中安装证书,以便所有用户都可以使用它。您已将它安装在当前用户的“我的”中。开发服务器以当前用户身份运行,这就是它工作的原因。

【讨论】:

【参考方案4】:

显然在配置的位置找不到证书。确保您使用哪个用户来运行该服务。也许该服务正在本地系统帐户或本地服务帐户或 IIS 用户上运行,并且您将证书安装为不同的用户?在 MMC 中添加一个管理单元以查看服务帐户或您用于服务的其他帐户中的证书(不是当前用户)。

【讨论】:

感谢您的建议。我在服务器上使用但客户端得到服务错误: 未提供客户端证书。在 ClientCredentials 中指定客户端证书。

以上是关于WCF 上的 X.509 证书?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 WCF 签署 X509 令牌

X.509证书生成

使用以下搜索条件找不到 X.509 证书----

X509Certificate - 密钥集不存在

x509证书格式

X509 证书生成