我正在尝试从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而没有实际的身体,但这部分不在我的控制范围内 - 它由第三部分决定 - 派对。我没有怀疑这是我问题的一个因素,但我在这里可能是非常错误的。
我花了很多时间在这上面并且碰壁了。
答案 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;测试,它不会有信任问题,但如果他们有自签名证书,你必须获取他们的证书并将其导入你的证书商店。