我有一个 REST Web 服务,它使用 WCF 客户端调用外部 SOAP Web 服务。此 REST Web 服务托管在我们测试环境中的 IIS 中。
当调用 REST Web 服务,然后调用外部 Web 服务(使用 WCF 客户端)时,在 IIS 中重新启动 REST Web 服务后,WCF 客户端的第一次调用会抛出安全协商异常。对 REST Web 服务的第二次调用以及间接调用以及所有后续调用都会成功。
To illustrate this, here's an image:
This 安全协商异常如下:
System.ServiceModel.Security.SecurityNegotiationException:无法使用权限“X”为 SSL/TLS 建立安全通道。
---> System.Net.WebException:请求已中止:无法创建 SSL/TLS 安全通道。
端点和绑定如下(通过添加服务引用生成,稍微修改了customBinding):
<endpoint address="https://..." binding="customBinding" bindingConfiguration="MyBinding" contract="WS_..." name="MyEndpoint" />
...
<customBinding>
<binding name="MyBinding">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="UserNameOverTransport" />
<httpsTransport requireClientCertificate="true" />
</binding>
</customBinding>
调用外部webservice的代码:
MyEndpointClient client = new MyEndpointClient("MyEndpoint");
client.ClientCredentials.UserName.UserName = authInfo.Username;
client.ClientCredentials.UserName.Password = authInfo.Password;
client.ClientCredentials.ClientCertificate.Certificate = authInfo.Certificate;
var result = client.requestInformation(parameters); // This fails the first time after IIS restart.
authInfo.Certificate 正在加载,如下所示:
authInfo.Certificate = new X509Certificate2(certificateBytes, certificatePassword);
更多信息:
- 当我在本地运行 REST Web 服务时,使用 WCF 客户端调用外部服务第一次(以及所有后续调用)工作正常。
- 我已通过添加服务引用将 SOAP Web 服务 WSDL 添加到项目中。
- 该网络服务需要用户名和密码以及证书。必须使用WSE3.0(Windows安全扩展),我不能使用WSE2.0。
- 在每种情况下证书都会正确加载,我已经使用 try-catch 创建了 X509Certificate2,它捕获 CryptographicException 并取消 REST-web 服务中的进一步处理(不会执行对 SOAP Web 服务的调用)。我已经验证我正在测试的证书是有效的。
- 添加外部 SOAP Web 服务 WSDL 时,它会生成自定义绑定(因此不是我手动尝试过的 basicHttpBinding 或 WsHttpBinding)。
- 外部 SOAP Web 服务支持 TLS 1.0、1.1 和 1.2(使用SSLLabs https://www.ssllabs.com/ssltest/analyze.html).
- Web 服务在测试环境中以管理员权限运行。
- 测试环境中的 IIS 在 Windows Server 2012 R2 Standard 上的版本 8.5.9600.16384 上运行
我已经尝试过但没有解决问题:
- 在第一次调用 SOAP Web 服务后,在 REST 调用的同一生命周期中第二次(甚至更多,最多 10 次)调用 SOAP Web 服务(重复行客户端.RequestInformation(参数))
- 在第一次失败的调用后创建新的 MyEndpointClient,并使用新客户端执行调用。
- 从证书存储加载证书
- 根据建议从文件加载证书这篇博文(参见提示 5) http://paulstovell.com/blog/x509certificate2
- 使用 WsHttpBinding 或 BasicHttpBinding
- 使用不同的认证方式在 customBinding 中的 security> 标记上。
- Using localClientSettings reconnectTransportOnFailure="true" />在安全>标签中
- Setting System.Net.ServicePointManager.Expect100Continue = true;
- Setting System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;(还尝试了 TLS 1.0 和 1.1 以及TL10 | TL11 | TL12立刻)
- Setting System.Net.ServicePointManager.ServerCertificateValidationCallback += (a,b,c,d) => true;(不是一个好主意,但值得一试)
- Setting client.ClientCredentials.UseIdentityConfiguration = false;(也使用Web.config配置使用行为)
- Setting client.ClientCredentials.SupportInteractive = false;(也使用Web.config配置使用行为)
有什么想法可以让 SOAP Web 服务的第一次调用与下一次调用一样稳定吗?