简体   繁体   English

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

[英]WCF Exception - The client certificate is not provided

WCF Exception - The client certificate is not provided. WCF异常-未提供客户端证书。 Specify a client certificate in ClientCredentials. 在ClientCredentials中指定客户端证书。

After reading most of what I have been able to find on this subject, and attempting many different options, I find I don't have any more hair to pull, and hence this post. 在阅读了我在该主题上能够找到的大部分内容并尝试了许多不同的选择之后,我发现我没有更多的头发可以拉了,因此可以发表这篇文章。

I wish to use SSL with a self-hosted WCF service, having security mode as TransportWithMessageCredential with HTTP transport. 我希望将SSL与自托管WCF服务一起使用,并将安全模式设置为具有HTTP传输的TransportWithMessageCredential。 I am using 2 dev machines and testing over a LAN. 我正在使用2台开发机并通过LAN进行测试。

As mentioned above, I have read and meticulously followed just about every example which demonstrates this, yet somehow still have issues with the certificates. 如上所述,我已经阅读并认真遵循了几乎所有能证明这一点的示例,但是在某种程度上仍然存在证书问题。

As far as the certificates are concerned, I have tried a number of things. 就证书而言,我尝试了很多事情。

The main jist of what I did was to follow what is given in http://msdn.microsoft.com/en-us/library/ff647171.aspx 我所做的主要事情是遵循http://msdn.microsoft.com/zh-cn/library/ff647171.aspx中给出的内容

I also used “How to: Use Certificate Authentication and Message Security in WCF Calling from Windows Forms” in http://msdn.microsoft.com/en-us/library/ff648360.aspx as a basic guide. 我还使用了http://msdn.microsoft.com/zh-cn/library/ff648360.aspx中的“如何:在Windows窗体的WCF调用中使用证书身份验证和消息安全性”作为基本指南。

I first tested the service and client using basicHttpBinding over Http in order to verify things. 我首先通过对HTTP使用basicHttpBinding来测试服务和客户端,以进行验证。

I then made changes for wsHttpBinding, SSL, and Certificates. 然后,我对wsHttpBinding,SSL和证书进行了更改。

When I “Add Service Reference” on the client dev PC, I receive an error as follows: 当我在客户端开发PC上“添加服务参考”时,收到如下错误:

  • Window Titled - 标题为-的窗口

Security Alert 安全警报

Visual Studio has detected a problem with the site's security certificate. Visual Studio检测到站点的安全证书有问题。

Issued By: RootCATest Issued to: TempCert Certificate is valid from--- 颁发者:RootCATest颁发者:TempCert证书的有效日期-

The security certificate issued by a company is not in the untrust list. 公司颁发的安全证书不在不信任列表中。 It might be trustable. 这可能是值得信赖的。

The security certificate date is valid. 安全证书日期有效。

The security certificate for host 'TempCert' does not match the name of the page you are trying to view. 主机“ TempCert”的安全证书与您尝试查看的页面的名称不匹配。

  • Do you want to proceed? 您要继续吗? - -

If I click “Yes” to proceed, and run the client code, an InvalidOperationException occurs with the following message. 如果单击“是”继续,然后运行客户端代码,则会发生InvalidOperationException并显示以下消息。

“The client certificate is not provided. “未提供客户证书。 Specify a client certificate in ClientCredentials.” 在ClientCredentials中指定客户端证书。”

The Service config is as follows: 服务配置如下:

<?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>

The client config is as follows: 客户端配置如下:

<?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>

The following is a Summary of the tasks I performed, based on the contents of numerous posts and documents. 以下是我根据大量帖子和文档的内容执行的任务的摘要。

  1. Created a self-signed CA certificate (named RootCATest) on the server, and placed it in the Trusted Root Certification Authorities Certificates folder of the Local Computer. 在服务器上创建一个自签名的CA证书(名为RootCATest),并将其放置在本地计算机的“受信任的根证书颁发机构证书”文件夹中。

  2. Created a certificate which is signed by the RootCATest certificate (named TempCert), on the server, and placed it in the Personal Certificates folder of the Local Computer. 在服务器上创建了一个由RootCATest证书(名为TempCert)签名的证书,并将其放在“本地计算机”的“个人证书”文件夹中。

  3. Exported the TempCert certificate and private key. 导出了TempCert证书和私钥。

  4. Copied the TempCert .cer and .pvk files to the client machine, and imported the TempCert Certificate into the Personal Certificates folder of the Local Computer. 将TempCert .cer和.pvk文件复制到客户端计算机,并将TempCert证书导入到本地计算机的“个人证书”文件夹中。

  5. Executed ICalcs.exe [private key path] /grant "NT AUTHORITY\\NETWORK SERVICE":R on the server machine, using the path to the private key for the TempCert certificate. 使用到TempCert证书的私钥的路径,在服务器计算机上执行ICalcs.exe [私钥路径] / grant“ NT AUTHORITY \\ NETWORK SERVICE”:R。

  6. Executed netsh http add sslcert ipport=oooo:8003 certhash=[TempCert thumbprint] appid=[{application id}] on the server machine 执行的netsh http在服务器计算机上添加sslcert ipport = oooo:8003 certhash = [TempCert指纹] appid = [{应用程序ID}]

I believe I am close to getting this working. 我相信我已经接近完成这项工作。

It seems pretty obvious that the app is not happy with the TempCert certificate, yet I have not been able to resolve this, and am pretty much stuck. 显然,该应用程序对TempCert证书不满意,但我仍无法解决此问题,并且陷入了困境。

Any assistance with respect to any problems in the given configurations, the steps I have followed in order to put the correct certificates in place, and those used to add access permissions and the sslcert entry, will be greatly appreciated. 对于在给定配置中出现的任何问题,我为将正确的证书放置到位而执行的步骤以及用于添加访问权限和sslcert条目的步骤所提供的任何帮助,将不胜感激。

Many thanks. 非常感谢。

After some further experimentation, I have noticed additional behavior. 经过进一步的实验后,我注意到了其他行为。

Steps taken are as follows: 采取的步骤如下:

I deleted both client and server certificates, and recreated them in accordance with ....codeproject.com/Articles/36683/9-simple-steps-to-enable-x-509-certificates-on-wcf 我删除了客户端和服务器证书,并根据.... codeproject.com/Articles/36683/9-simple-steps-to-enable-x-509-certificates-on-wcf重新创建了它们

I added the new sslcert using netsh. 我使用netsh添加了新的sslcert。 I then exported the client certificate from the server and imported it into the client store. 然后,我从服务器导出了客户端证书,并将其导入到客户端存储中。

I modified the service app.config with the new certificates info, and started the service. 我使用新的证书信息修改了服务app.config,并启动了服务。

I modified the client app.config as follows: 我修改了客户端app.config,如下所示:

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

I updated the Service Reference. 我更新了服务参考。 The update procedure once again issued a Security Alert as before. 更新过程再次像以前一样发布了安全警报。

I then executed the client, and received this error: 然后,我执行了客户端,并收到此错误:

"The client certificate is not provided. Specify a client certificate in ClientCredentials." “未提供客户端证书。在ClientCredentials中指定客户端证书。”

I then set a breakpoint on "client = new WCFService.Client();" 然后,在“ client = new WCFService.Client();”上设置一个断点。 and checked the "client" instance. 并检查了“客户端”实例。 The value of client.ClientCredentials.ClientCertificate.Certificate = null. client.ClientCredentials.ClientCertificate.Certificate = null的值。

I then added the following in code after "client = new WCFService.Client();": 然后,在“ client = new WCFService.Client();”之后的代码中添加以下内容:

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);
}
}

After execution of this code, client.ClientCredentials.ClientCertificate.Certificate contained the certificate. 执行此代码后,client.ClientCredentials.ClientCertificate.Certificate包含证书。

When then executing "client.Open();" 然后执行“ client.Open();”时 , an exception is thrown with the following contents. ,将引发以下内容的异常。

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. 基础连接已关闭:无法为SSL / TLS安全通道建立信任关系。 The remote certificate is invalid according to the validation procedure. 根据验证过程,远程证书无效。 Could not establish trust relationship for the SSL/TLS secure channel with authority 无法使用授权建立SSL / TLS安全通道的信任关系

If anyone with knowledge of what may be happening here could shed some light on this I will be very grateful. 如果任何人知道这里可能发生的事情,对此可以有所启发,我将非常感激。

The last error message indicates that your server is requesting a client certificate from the client (the server has to ask), and the client is providing a certificate, but the server is not able to determine whether the client certificate is valid based on information available on the server machine. 最后一条错误消息表明您的服务器正在向客户端请求客户端证书(服务器必须询问),并且客户端正在提供证书,但是服务器无法根据可用信息确定客户端证书是否有效在服务器计算机上。

Since you are using self-signed certificates (not CA issued certificates), you need to tell the server how to validate the client certificates. 由于您使用的是自签名证书(不是CA颁发的证书),因此需要告诉服务器如何验证客户端证书。 You may need to install the client certificates in the server's My/LocalMachine/Trusted People cert store so that WCF's default certificate validation can find them, or implement your own custom client certificate validator on the server. 您可能需要在服务器的My / LocalMachine / Trusted People证书存储中安装客户端证书,以便WCF的默认证书验证可以找到它们,或者在服务器上实现自己的自定义客户端证书验证器。 (See WebHttpBinding.Credentials.ClientCertificate.Authentication.CertificateValidationMode and WebHttpBinding.Credentials.ClientCertificate.Authentication.CustomCertificateValidator ) (请参阅WebHttpBinding.Credentials.ClientCertificate.Authentication.CertificateValidationModeWebHttpBinding.Credentials.ClientCertificate.Authentication.CustomCertificateValidator

I did notice that in your endpoint definition, you did not refer to the behavior that you defined. 我确实注意到,在endpoint定义中,您没有引用定义的behavior It looks as if you are doing the equivalent, by-hand via some code. 看起来您正在通过一些代码手动进行等效操作。 It might be simpler to just wire-it-up in the config. 仅在配置中进行连线可能会更简单。

I would expect your endpoint to look (more) like this: 我希望您的端点看起来像这样(更多):

      <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>

This was the solution, when I was getting the error "The client certificate is not provided. Specify a client certificate in ClientCredentials". 当出现错误“未提供客户端证书。在ClientCredentials中指定客户端证书”时,这就是解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM