简体   繁体   English

带有证书的 WebRequest 在第一次调用时失败,并在所有后续调用中成功

[英]WebRequest with certificate fails on first call and succeeds all subsequent calls

Infrastructure基础设施

I have an old .NET Framework application that I migrated from an old server.我有一个从旧服务器迁移的旧 .NET 框架应用程序。 It's in 4.6.2 running on Windows Server 2012 R2.它在 4.6.2 中运行在 Windows Server 2012 R2 上。

The forms application makes a call to a WCF service running also in the same server under the same application pool and the WCF service makes a WebRequest call to an external service. forms 应用程序调用 WCF 服务,该服务也在同一应用程序池下的同一服务器中运行,并且 WCF 服务对外部服务进行 WebRequest 调用。

The external call requires certificates for the SSL/TLS handshake.外部调用需要 SSL/TLS 握手证书。

In the old server the certificates are attached to the request, but in the new server this wasn't working and we had to add them in the trust store.在旧服务器中,证书附加到请求中,但在新服务器中,这不起作用,我们不得不将它们添加到信任库中。 This might be a important clue to the question below.这可能是下面问题的重要线索。

The problem问题

The WCF service makes the call to the external service and the first call (after deploying or restarting the app) is always an error The request was aborted: Could not create SSL/TLS secure channel. WCF 服务调用外部服务,第一次调用(在部署或重新启动应用程序后)总是错误The request was aborted: Could not create SSL/TLS secure channel.

However ALL subsequent calls work successfully.但是,所有后续调用都成功运行。 It's almost as if the certificate isn't properly loaded into the user profile on the first call, but afterwards it is.就好像证书在第一次调用时没有正确加载到用户配置文件中一样,但之后就是这样。

This is causing issues after deploying a new version, all first calls fail, which impacts live traffic.这会在部署新版本后导致问题,所有首次调用都失败,这会影响实时流量。 We have the same configuration on 6 boxes, under a load balancer and it's identical behaviour on all 6 boxes.我们在负载均衡器下的 6 个盒子上具有相同的配置,并且在所有 6 个盒子上的行为相同。

I want to fix this so that the call succeeds on the first call.我想解决这个问题,以便在第一次通话时通话成功。

The code编码

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

Things I have tried我尝试过的事情

  • This article titled “WCF Client: First call fails, second call succeeds” is certificate related and extremely promising.这篇题为“WCF 客户端:第一次调用失败,第二次调用成功”的文章与证书相关,非常有前途。 However, the suggestion to bypass HTTP status 100 with ServicePointManager.Expect100Continue = true;但是,建议使用ServicePointManager.Expect100Continue = true; didn't work.没用。

  • Tried setting the protocol to TLS 1.2: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;尝试将协议设置为 TLS 1.2: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

  • Tried setting X509KeyStorageFlags.MachineKeySet as per this suggestion尝试按照此建议设置X509KeyStorageFlags.MachineKeySet

  • From same suggestion, tried changing the application pool identity to Network Service, LocalSystem and LocalService none of which worked.根据相同的建议,尝试将应用程序池标识更改为 Network Service、LocalSystem 和 LocalService,但均无效。

Other info其他信息

The Application pool is the recommended identity `ApplicationPoolIdentity" and the Load User Profile setting is set to true, otherwise the certificates do not load.应用程序池是推荐的身份“ApplicationPoolIdentity”,并且“加载用户配置文件”设置设置为 true,否则不会加载证书。

I'm running out of ideas what to do next and need some help understanding and fixing this behaviour我想不出下一步该做什么,需要一些帮助来理解和修复这种行为

It seems to work now by adding these keys:现在通过添加这些键似乎可以工作:

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

Thanks谢谢

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

相关问题 第一次移动呼叫的XHR错误失败,后续呼叫均全部成功 - XHR error on first mobile call is failing, subsequent calls are all successful C#,cmd行应用程序在第一次调用时创建对象,在所有后续调用中使用对象 - C#, cmd line application creates object on first call, uses object in all subsequent calls ValidateCredentials()在首次调用时返回FALSE,但在随后的调用中返回TRUE - ValidateCredentials() returns FALSE on First Call but TRUE on Subsequent Calls 第一次失败后,.Net WebRequest始终失败 - .Net WebRequest Fails all the time after first failure CORS 错误:预检请求成功,后续 GET 请求失败 - CORS error: Preflight request succeeds, subsequent GET request fails 调用`Environment.GetEnvironmentVariable`会影响后续调用 - Call to `Environment.GetEnvironmentVariable` affects subsequent calls 停止所有后续呼叫以订阅反应式分机 - Stopping all subsequent calls to subscribe in reactive extensions Win Phone7 WebRequest第一次通话未返回 - Win Phone7 WebRequest Not returning on first call WCF客户端。 客户证书。 第一次呼叫成功,第二次呼叫失败 - WCF client. Client Certificate. First call success, Second call fails 为什么 WebRequest 总是在第一个请求上超时,但从不在任何后续请求上超时 - Why does WebRequest timeout always on the first request, but never on any subsequent ones
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM