Azure,ASP.NET Core 2.0,使用客户端证书使用HttpClient调用Post导致“无法识别客户端证书凭据”

时间:2018-01-31 20:25:45

标签: c# azure asp.net-core certificate httpclient

我正在尝试从ASP.NET Core(2.0.2)Web API(在Controller中)调用第三方的基于HTTP的API。

在非Azure环境(Windows 7 Boxes)中运行时成功。 在Azure中的App Service中运行时出现错误,并显示错误“无法识别客户端证书凭据”。 代码和证书在环境之间是相同的。 两者都在IIS中运行。

我已将代码缩减以隔离我的问题,如下所示。我在这里更改了密码和URL详细信息,原因很明显。

[HttpGet]
public async Task<IActionResult> Get()
{
    string response = null;

    using (HttpClientHandler handler = new HttpClientHandler())
    {
        handler.ClientCertificateOptions = ClientCertificateOption.Manual;
        handler.SslProtocols = SslProtocols.Tls12;
        handler.ClientCertificates.Add(new X509Certificate2("Certificate/Cert.pfx", "<password-removed>"));
        using (HttpClient client = new HttpClient(handler))
        {
            using (HttpResponseMessage responseMessage = await client.PostAsync("https://some-domain.com/action.asp?sourceid=123&key=10101", null))
            {
                response = await responseMessage.Content.ReadAsStringAsync();
            }
        }
    }

    return Ok(response);
}

生成的异常和callstack如下:

  

System.Net.Http.HttpRequestException:发送时发生错误   请求。   ---&GT; System.Net.Http.WinHttpException:无法识别客户端证书凭据   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at   System.Threading.Tasks.RendezvousAwaitable1.GetResult()at   System.Net.Http.WinHttpHandler.d__105.MoveNext()   ---内部异常堆栈跟踪结束---在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult()   在   System.Net.Http.HttpClient.d__58.MoveNext()   ---抛出异常的前一个位置的堆栈跟踪结束--- \ TestController.cs:第32行

另一个有趣的事情是我可以使用CURL在Azure App Service Console中成功执行此POST,如下所示。这里使用的.pem文件是从C#代码中使用的.pfx文件生成的。

curl -s --data "" --cert .\Cert.pem:<password-removed> "https://some-domain.com/action.asp?sourceid=123&key=10101"

更新

我重构了代码库以简化问题的重复。我现在正在使用一个控制台应用程序,我将通过Kudu上传到Azure中的App Service并在Kudu控制台中运行。它失败的原因与上面相同。

static void Main(string[] args)
{
    Console.WriteLine("Starting v3...");
    string response = null;

    try
    {
        using (HttpClientHandler handler = new HttpClientHandler())
        {
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.SslProtocols = SslProtocols.Tls12;
            Console.WriteLine("Loading Cert...");
            var cert = new X509Certificate2(certFilePath, certPassword);
            Console.WriteLine("Verifying Cert...");
            bool result = cert.Verify();
            Console.WriteLine($"Verified Cert: {result}"); // Variable result is 'True'here.
            handler.ClientCertificates.Add(cert);

            using (HttpClient client = new HttpClient(handler))
            {
                HttpContent content = new System.Net.Http.StringContent("");
                Console.WriteLine("Posting...");
                using (HttpResponseMessage responseMessage = client.PostAsync(url, content).Result) //  FAILS HERE!
                {
                    Console.WriteLine("Posted...");
                    Console.WriteLine("Reading Response...");
                    response = responseMessage.Content.ReadAsStringAsync().Result;
                    Console.WriteLine($"Response: {response}");
                }
            }
        }
    }
    catch (Exception exc)
    {
        Console.WriteLine("BOOM!!!");
        exc = LogException(exc);
    }

    Console.WriteLine("Done!");
    Console.ReadLine();
}

请注意:我知道这是不寻常的,因为我正在使用查询参数执行POST而没有实际的身体,但这部分不在我的控制范围内 - 它由第三部分决定 - 派对。我没有怀疑这是我问题的一个因素,但我在这里可能是非常错误的。

我花了很多时间在这上面并且碰壁了。

2 个答案:

答案 0 :(得分:1)

解决方案比预期容易得多。我需要WEBSITE_LOAD_CERTIFICATES键和Azure App Service应用程序设置中的值的指纹,但只有在Web服务器的上下文中运行时才会选中此键。所以我以前尝试隔离问题的控制台应用程序只会让我更加痛苦,因为它没有看到这些设置。

这篇文章是我解决这个问题的原因。

https://docs.microsoft.com/en-us/azure/app-service/app-service-web-ssl-cert-load

答案 1 :(得分:0)

您是否已将其服务器证书添加到证书库?客户端证书用于相互身份验证情况,您要向他们发送代表您的证书。如果他们的证书通过&#34;众所周知的&#34;测试,它不会有信任问题,但如果他们有自签名证书,你必须获取他们的证书并将其导入你的证书商店。