Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WCF客户端:第一次调用失败,第二次调用成功_C#_Wcf_Wcf Binding - Fatal编程技术网

C# WCF客户端:第一次调用失败,第二次调用成功

C# WCF客户端:第一次调用失败,第二次调用成功,c#,wcf,wcf-binding,C#,Wcf,Wcf Binding,我有一个REST Web服务,它使用WCF客户端调用外部SOAP Web服务。此REST Web服务托管在我们测试环境的IIS中 调用REST Web服务时,该服务随后调用外部Web服务(使用WCF客户端),在IIS中重新启动REST Web服务后,WCF客户端的第一次调用会引发SecurityNegotiationException。对RESTWebService的第二次调用,以及间接调用和所有后续调用成功 为了说明这一点,以下是一张图片: 此SecurityNegotiationExcep

我有一个REST Web服务,它使用WCF客户端调用外部SOAP Web服务。此REST Web服务托管在我们测试环境的IIS中

调用REST Web服务时,该服务随后调用外部Web服务(使用WCF客户端),在IIS中重新启动REST Web服务后,WCF客户端的第一次调用会引发SecurityNegotiationException。对RESTWebService的第二次调用,以及间接调用和所有后续调用成功

为了说明这一点,以下是一张图片:

此SecurityNegotiationException如下所示:

authInfo.Certificate = new X509Certificate2(certificateBytes, certificatePassword);
System.ServiceModel.Security.SecurityNegotiationException:无法为具有权限“X”的SSL/TLS建立安全通道。 --->System.Net.WebException:请求被中止:无法创建SSL/TLS安全通道

端点和绑定如下(通过添加服务引用生成,稍微修改了customBinding):

正在按如下方式加载authInfo.证书:

authInfo.Certificate = new X509Certificate2(certificateBytes, certificatePassword);
更多信息:

  • 当我运行RESTWebService local时,使用WCF客户端调用外部服务在第一次(以及所有后续调用)时都可以正常工作
  • 我已经通过添加服务引用向项目中添加了SOAP webservice WSDL
  • 此Web服务需要用户名和密码以及证书。必须使用WSE3.0(Windows安全扩展),我不能使用WSE2.0
  • 在每种情况下,证书都能正确加载,我使用try-catch创建X509Certificate2,它捕获加密异常并取消REST Web服务中的进一步处理(不会执行对SOAP Web服务的调用)。我已经验证了我正在测试的证书是有效的
  • 添加外部SOAP webservice WSDL时,它会生成一个自定义绑定(因此不是我手动尝试的basicHttpBinding或WsHttpBinding)
  • 外部SOAP Web服务支持TLS1.0、1.1和1.2(使用测试)
  • webservice在测试环境中以管理员权限运行
  • 测试环境中的IIS在Windows Server 2012 R2标准上的版本8.5.9600.16384上运行
我尝试过但未解决的问题:

  • 在REST调用的同一生命周期中,在第一次调用后第二次调用SOAP Web服务(以及更多次,最多10次)(复制了line client.RequestInformation(参数))
  • 在第一次调用失败后创建新的MyEndpointClient,并使用新客户端执行调用
  • 从证书存储加载证书
  • 根据来自的建议,从文件加载证书
  • 使用WsHttpBinding或BasicHttpBinding
  • 在customBinding中的security>标记上使用不同的authenticationMode
  • 在security>标记中使用localClientSettings reconnectTransportOnFailure=“true”/>
  • 设置System.Net.ServicePointManager.Expect100Continue=true
  • 设置System.Net.ServicePointManager.SecurityProtocol=System.Net.SecurityProtocolType.Tls12;(同时尝试TLS 1.0和1.1以及Tls10 | Tls11 | Tls12)
  • 设置System.Net.ServicePointManager.ServerCertificateValidationCallback+=(a、b、c、d)=>true;(不是个好主意,但值得一试)
  • 设置client.ClientCredentials.UseIdentityConfiguration=false;(也使用Web.config配置,使用行为)
  • 设置client.ClientCredentials.SupportInteractive=false;(也使用Web.config配置,使用行为)

想让对SOAP Web服务的第一次调用与下一次调用一样稳定吗?

出于某种原因,这只发生在一个测试服务器上,而不是其他服务器上。 调用外部SOAP Web服务的跟踪日志显示内部函数
AcquireCredentialsHandle
失败,错误代码
0X8009030D

经过进一步的调查,我发现有几个证书(来自外部SOAP web服务)安装在相关服务器上。它们似乎与对外部SOAP Web服务的调用相冲突。删除这些证书后,第一次调用现在成功

更新:我再次遇到同样的问题,但现在在我的开发机器上。清理证书没有帮助,并且所有请求都失败,出现相同的SecurityNegotiationException。为了解决这个问题,我添加了HTTP 100状态代码的传递,并强制连接到TLS 1.2:

ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

请注意,我在初始化WCF客户端(问题帖子中的MyEndpointClient)之前添加了此代码,以确保WCF客户端使用这些设置。

tl;dr.我认为部分症状来自WCF通道属性:在发生故障后,它仍然存在故障。确保备份并创建新通道(客户端对象)。
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;