繁体   English   中英

在 Azure 函数中使用 RestSharp 调用 HTTPS 会出现“无法建立 SSL 连接”

[英]Calling HTTPS using RestSharp within a Azure function gives "The SSL connection could not be established"

如何使用特定证书从 Azure Function 中调用 HTTPS 站点以建立 HTTPS 连接?

我有一个 Azure 函数,需要使用证书与远程服务器进行通信。 远程服务器是一家银行。

开始安装证书并在本地运行 Azure 函数模拟器并建立连接。

上传到 Azure 我收到这条消息

The SSL connection could not be established, see inner exception. Authentication failed, see inner exception. 

我尝试将证书包含在 Azure Function SLL 下我将证书链中的所有证书安装为公共证书 (.cer) 和私有证书 (.pfx)

尝试使用指纹获取证书失败。

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
    {
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection certificates = store.Certificates;

        foreach (var certificate2 in certificates)
        {
            if (certificate2.Thumbprint.ToLower() == thumbprint.ToLower())
            {
                return certificate2;
            }
        }
     }

在这种情况下,我尝试使用循环而不是使用内置函数查找证书以使用 Tumbprint 查找证书

当这不起作用时,我将证书 (.pfx) 作为文件提供。

获取证书有效。

certificate = new X509Certificate2(filename, password, X509KeyStorageFlags.MachineKeySet);

Azure 函数需要 X509KeyStorageFlags.MachineKeySet,但在运行本地 Azure 函数模拟器时不需要

RestSharp 在 Azure 函数模拟器中工作

var client = new RestClient(BaseUrl)
{
    Timeout = 180000,
    ClientCertificates = new X509CertificateCollection() { cert }

};
client.AddDefaultHeader("Content-type", "application/json");
var request = new RestRequest(Query, Method.POST);
request.Parameters.Clear();
request.AddParameter("application/json", jsonSwish, ParameterType.RequestBody);
IRestResponse response = await client.ExecuteTaskAsync(request);

我收到“无法建立 SSL 连接...”

我在创建客户端之前添加了这个但它没有解决问题

ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

然后我创建了一个简单的 PHP,它在输入中包含 HTTP,并使用 CURL 和所需的证书作为 CURL 的参数创建 HTTPS 输出。 这有效,但是一个丑陋的解决方案。

如何使用特定证书从 Azure Function 中调用 HTTPS 站点以建立 HTTPS 连接?

从描述中可以看出,Web 应用程序中的代码向使用仅在您的网络中受信任的证书的后端服务发出 HTTPS 请求。 由于 Web 应用服务器没有受信任的根证书,因此失败并显示“不可信”错误。 如果我误解了配置,请告诉我。

但是,以下信息基于该特定假设。

遗憾的是,出于安全考虑,无法将证书导入 Azure Web Apps 中的受信任根存储。 解决此错误的唯一选择是处理类似于此处描述的应用程序代码中的验证: https : //stackoverflow.com/a/34204814 我们过去曾成功地使用过这些步骤,例如:

  1. 创建新证书以获取要上传的 PFX 文件。
  2. 将 PFX 上传到 SSL 证书区域中的应用服务
  3. 按照此链接中的步骤 1 和 2 加载证书: https : //azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/
  4. 添加上述链接中第 3 步中的代码和此处的代码的组合: Azure Web App call on-prem service with Self-Signed SSL Cert 本质上,从证书存储中获取证书,但从 ServerCertificateValidationCallback 函数中获取,如果证书匹配以进行验证,则返回 true。 代码如下所示:

 ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { if (sslPolicyErrors == SslPolicyErrors.None) { return true; } var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); certStore.Open(OpenFlags.ReadOnly); var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, "THUMBPRINT", false); if (certCollection.Count > 0) { var validCertificate = certCollection[0]; var passedCert = new X509Certificate2(certificate); certStore.Close(); return validCertificate.Equals(passedCert); } certStore.Close(); return false; };

在 Startup for .netcore 中添加如何使用 HttpClient 执行此操作的更多详细信息。 你会写一些东西,比如builder是你的IWebJobsBuilder

builder.Services.AddHttpClient("HttpClientWithSSLCustom).ConfigurePrimaryHttpMessageHandler(() =>
            new HttpClientHandler
            {
                ClientCertificateOptions = ClientCertificateOption.Manual,
                ServerCertificateCustomValidationCallback =
                    (httpRequestMessage, cert, cetChain, policyErrors) =>
                    {
                        if (policyErrors == SslPolicyErrors.None)
                        {
                            return true;
                        }

                        var validCertificate = GetCertThumbprint("Thumbnail from config maybe")
                        var passedCert = new X509Certificate2(cert);

                        return validCertificate.Equals(passedCert);
                    }

            });

对于函数GetCertThumbprint使用下面经过调整的代码

X509Certificate2 GetCertThumbprint(string thumbprint)
    {
        X509Certificate2 cert = null;
        using (var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
        {
            certStore.Open(OpenFlags.ReadOnly);
            var certCollection = certStore.Certificates.Find(
                X509FindType.FindByThumbprint,
                thumbprint,
                false);
            // Get the first cert with the thumbprint
            if (certCollection.Count > 0)
            {
                cert = certCollection[0];
            }
        }
        return cert;
    }

然后在您的代码中的任何地方,只需使用新客户端,如下所示

client = clientFactory.CreateClient("HttpClientWithSSLCustom");

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM