WCF 客户端。客户证书。第一次调用成功,第二次调用失败

Posted

技术标签:

【中文标题】WCF 客户端。客户证书。第一次调用成功,第二次调用失败【英文标题】:WCF client. Client Certificate. First call success, Second call fails 【发布时间】:2019-10-20 08:26:19 【问题描述】:

我正在尝试使用 c# .NET 4.5 使用soap11 和客户端证书凭据通过https 连接到soap Web 服务。我使用vs的工具来添加服务引用,它为我创建了一个soap客户端。

我已经创建了一个 customBinding 来通过 soap11 完成 https:

App.config

<system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="*****" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="00:05:00" sendTimeout="00:05:00">
          <textMessageEncoding messageVersion="Soap11"/>
          <httpsTransport useDefaultWebProxy="false" requireClientCertificate="true" allowCookies="false" />
        </binding>
      </customBinding>
    </bindings>
    <client>
        <endpoint address="******************"
            behaviorConfiguration="******************"
            binding="customBinding" bindingConfiguration="******************"
            contract="******************"
            name="******************" />
    </client>
  <behaviors>
    <endpointBehaviors>
      <behavior name="******************">
        <clientCredentials>
          <clientCertificate findValue="******************" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
        </clientCredentials>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

c#代码:

     var client = new IConsultService.ConsultServiceClient();
     client.consult("1"); 
     client.consult("1"); <!-- fail error 404 - there was not endpoint listening at

如果我在没有证书的情况下发布接收 tomcat 404,如果我第一次发送客户端证书工作正常,并且在我看来我被重定向了。问题是在第二次请求失败(404)时,如果我再次实例化客户端失败。只有在停止应用程序并重新启动时才能再次工作。似乎有些东西缓存在程序的静态堆栈中。

由于是 404,我的猜测是来自客户端证书,如果我在没有证书的情况下请求,则错误是相同的。

我尝试以编程方式创建绑定,设置 ClientBase.CacheSetting = CacheSetting.AlwaysOff 没有运气。

编辑1: 使用 System.Net.HttpWebRequest 发生同样的情况,第一个请求 ok,第二个请求 404。

编辑2: 握手第一个请求发送“证书,客户端密钥交换”和第二个请求“更改密码密钥交换”似乎有一些东西

有没有办法强制关闭通道并始终发送“证书,客户端密钥交换”?

谢谢

【问题讨论】:

有趣的是我有相反的问题。第一次调用失败,后续调用都成功。 【参考方案1】:

首先,如果我们用X509certificate对客户端进行认证,我们通常需要在服务器和客户端之间建立信任关系,即我们应该在受信任的根证书颁发机构中安装彼此的证书,并且客户端需要提供一个Identity 确认服务器的身份(这通常是服务器证书的公钥,或者主机名)

<endpoint address="net.tcp://10.157.13.69:4386/" binding="netTcpBinding"
    bindingConfiguration="NetTcpBinding_ITestService" contract="ServiceReference1.ITestService"
    name="NetTcpBinding_ITestService">
    <identity>
        <dns value="vabqia969VM" />
    </identity>
</endpoint>

其次,我怀疑问题是由 TLS 版本引起的。您是否尝试过升级这些项目的 Dotnetframework?至少4.6.2以上。请参考以下文档。https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls 如果问题仍然存在,请随时告诉我。

【讨论】:

嗨@abraham,连接在第一个请求中有效,但在第二个请求中无效。似乎通道简化了握手,因此在第二个请求中不发送“客户端密钥交换”,似乎有某种会话正在进行。问题是我每次都需要像第一次连接一样发送客户端密钥交换。但在引擎盖下.NET 不允许我这样做。只有完成该过程并重新启动它才能工作。关于 TLS 版本我用 TLS11 和 TLS12 一样的问题。 您是否尝试将 Security 元素添加到服务器端的自定义绑定中?它可以指定验证客户端的协商过程。 嗨@Abraham问题是服务器没有正确恢复TLS会话,我没有在.NET(客户端)上找到一个参数来指示在每个要求。我将它解析为具有该参数的其他语言,但如果 .NET 有它会很棒。

以上是关于WCF 客户端。客户证书。第一次调用成功,第二次调用失败的主要内容,如果未能解决你的问题,请参考以下文章

WCF 客户端证书验证 + Windows 身份验证

使用ssl和客户端证书的Wcf:请求svc succes wcf调用返回403.16

WCF 不活动超时

WCF 服务中的自定义客户端证书和用户名验证

如何在 WCF 客户端中接受自签名 SSL 证书?

来自同一主机上的 Invoke-WebRequest 的 WCF 客户端证书身份验证