【问题标题】:Calling HTTPS using RestSharp within a Azure function gives "The SSL connection could not be established"在 Azure 函数中使用 RestSharp 调用 HTTPS 会给出“无法建立 SSL 连接”
【发布时间】:2019-04-16 05:42:43
【问题描述】:

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

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

安装证书并在本地运行 Azure Function Emulator 并建立连接。

上传到 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 Function Emulator 时不需要

RestSharp 在 Azure Function Emulator 中运行

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 连接?

【问题讨论】:

  • 正如错误所说see inner exception。什么是内部异常?发布 full 异常,包括其调用堆栈和任何内部异常。您可以使用Exception.ToString() 轻松获得。这将告诉您问题是 TLS1.2(现在所有主要提供商都需要 TLS1.2)还是证书问题
  • 不需要从 4.6 开始也不应该设置ServicePointManager.SecurityProtocol,只要您运行的是受支持的操作系统版本.运行时将选择使用操作系统默认值,这意味着一旦 TLS1.3 可用,它将选择它。即使您使用较旧的运行时,允许 SecurityProtocolType.Tls 也是一个坏主意 - 该协议被认为是不安全的。

标签: c# azure ssl azure-functions restsharp


【解决方案1】:

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

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

很遗憾,出于安全考虑,无法将证书导入 Azure Web 应用程序中的受信任根存储。解决此错误的唯一选择是在应用程序代码中处理验证,类似于此处描述的内容: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 calling 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;
            };
 

【讨论】:

    【解决方案2】:

    在 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");
    

    【讨论】:

      猜你喜欢
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      • 2021-02-01
      相关资源
      最近更新 更多