我试图从ASP.NET核心(2.0.2)的Web API(在控制器内)调用第三方的基于HTTP的API。
在非Azure的环境中运行(Windows 7的框),当它成功。 与误差范围内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(任务task)在System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult()在System.Net.Http.HttpClient.d__58.MoveNext()---从以前的位置,其中的例外是堆栈跟踪的结尾抛出--- \ TestController.cs:线32
另一个有趣的事情是,我可以使用curl如下成功地执行这个帖子在Azure的应用服务控制台。 这里使用的.PEM文件从C#代码中使用的.pfx文件生成。
curl -s --data "" --cert .\Cert.pem:<password-removed> "https://some-domain.com/action.asp?sourceid=123&key=10101"
更新
我重构代码库,以简化问题的重复。 现在,我使用它,我上传到通过捻的应用服务在Azure和在库杜控制台运行一个控制台应用程序。 它失败,与上述相同的异常。
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并没有实际的身体,但这一部分是不是在我的控制-它是由第三方所决定的。 我没有怀疑这是我的问题的一个因素,但我可能是大错。
我花了很多时间在这个伟大的交易,都碰了壁。