首页 > 解决方案 > 带有证书的 WebRequest 在第一次调用时失败,并在所有后续调用中成功

问题描述

基础设施

我有一个从旧服务器迁移的旧 .NET Framework 应用程序。它在 Windows Server 2012 R2 上运行的 4.6.2。

表单应用程序调用也在同一应用程序池下的同一服务器中运行的 WCF 服务,并且 WCF 服务对外部服务进行 WebRequest 调用。

外部调用需要 SSL/TLS 握手证书。

在旧服务器中,证书附加到请求中,但在新服务器中,这不起作用,我们不得不将它们添加到信任库中。这可能是下面问题的重要线索。

问题

WCF 服务调用外部服务,第一次调用(在部署或重新启动应用程序后)总是错误The request was aborted: Could not create SSL/TLS secure channel.

但是,所有后续调用都成功运行。就好像证书在第一次调用时没有正确加载到用户配置文件中一样,但之后就是这样。

这会在部署新版本后导致问题,所有首次调用都失败,这会影响实时流量。我们在负载均衡器下的 6 个盒子上具有相同的配置,并且在所有 6 个盒子上的行为相同。

我想解决这个问题,以便在第一次通话时通话成功。

编码

    public static Stream SendRequest(string url, string requestXml, string clientKeyBase64, string clientKeyPassword, int requestTimeout)
    {
        Stream os = null;
        HttpWebRequest req = null;
        WebResponse resp = null;
        byte[] bytes;

        try
        {
            req = (HttpWebRequest)WebRequest.Create(url);
            req.Timeout = requestTimeout;
            req.ContentType = "application/xml; charset=utf-8";
            req.Method = "POST";
            bytes = Encoding.ASCII.GetBytes(requestXml);
            req.ContentLength = bytes.Length;

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

            if (!string.IsNullOrWhiteSpace(clientKeyBase64))
            {
                var cert = new X509Certificate2(Convert.FromBase64String(clientKeyBase64), clientKeyPassword);
                req.ClientCertificates.Add(cert);
            }
            using (os = req.GetRequestStream())
            {
                os.Write(bytes, 0, bytes.Length);
            }

            using (resp = req.GetResponse())
            {
                using (var stream = resp.GetResponseStream())
                {
                    MemoryStream memStream;
                    memStream = new MemoryStream();
                    stream.CopyTo(memStream);
                    memStream.Seek(0, SeekOrigin.Begin); // Required to reset stream pointer at the beginning
                    return memStream;
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

我尝试过的事情

其他信息

应用程序池是推荐的身份“ApplicationPoolIdentity”,并且“加载用户配置文件”设置设置为 true,否则不会加载证书。

我想不出下一步该做什么,需要一些帮助来理解和修复这种行为

标签: c#iiswebrequestx509certificate2.net-4.6.2

解决方案


现在通过添加这些键似乎可以工作:

X509KeyStorageFlags.UserKeySet |                                                                                                                                 
X509KeyStorageFlags.MachineKeySet |                                                                                                                                  
X509KeyStorageFlags.PersistKeySet |                                                                                                        
X509KeyStorageFlags.Exportable

谢谢


推荐阅读