【发布时间】:2018-07-11 01:50:45
【问题描述】:
我正在尝试从 ASP.NET Core (2.0.2) Web API(在控制器内)调用第三方基于 HTTP 的 API。
在非 Azure 环境(Windows 7 Box)中运行时成功。 在 Azure 中的应用服务中运行时失败,并出现错误“无法识别客户端证书凭据”。 环境之间的代码和证书是相同的。 两者都在 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);
}
产生的异常和调用栈如下:
System.Net.Http.HttpRequestException:发送时出错 请求。 ---> System.Net.Http.WinHttpException:客户端证书凭证在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Threading.Tasks.RendezvousAwaitable1.GetResult() 在 System.Net.Http.WinHttpHandler.d__105.MoveNext() --- 内部异常堆栈跟踪结束 --- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 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:line 32
另一个有趣的事情是,我可以使用 CURL 在 Azure 应用服务控制台中成功执行此 POST,如下所示。此处使用的 .pem 文件是从 C# 代码中使用的 .pfx 文件生成的。
curl -s --data "" --cert .\Cert.pem:<password-removed> "https://some-domain.com/action.asp?sourceid=123&key=10101"
更新
我已经重构了代码库以简化问题的重复。我现在正在使用一个控制台应用程序,它通过 Kudu 上传到 Azure 中的应用服务并在 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,但这部分不在我的控制范围内 - 它由第三部分决定 -派对。我没有怀疑这是我的问题的一个因素,但我在这里可能大错特错。
我在这方面花了很多时间,结果碰壁了。
【问题讨论】:
标签: c# azure asp.net-core certificate httpclient