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

时间:2019-04-16 05:42:44

标签: c# azure ssl azure-functions restsharp

如何使用特定证书从Azure功能中调用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 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功能中调用HTTPS站点以建立HTTPS连接?

2 个答案:

答案 0 :(得分:0)

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

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

很遗憾,由于安全方面的考虑,无法将证书导入Azure Web Apps中的受信任的根存储。解决此错误的唯一方法是使用类似于以下说明的应用程序代码来处理验证:https://stackoverflow.com/a/34204814。过去,我们已经成功地使用了这些步骤,例如:

  1. 创建新证书以获得要上传的PFX文件。
  2. 在“ SSL证书”区域中将PFX上载到应用程序服务
  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;
            };
 

答案 1 :(得分:0)

添加更多详细信息,说明如何在.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");