C#,我该如何将证书添加到HttpClientHandler中?

11

我需要向需要证书授权的Web API发送数据。但是我不知道如何将证书添加到.Net 4.5中的处理程序中。以下是代码:

// Import the certificate
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(pathToCertificate, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

using (var handler = new HttpClientHandler() { })
{
    using (var client = new HttpClient(handler))
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


        // Build the JSON
        string json = JsonConvert.SerializeObject(userData, Formatting.Indented);
        Console.WriteLine(json);

        var httpContent = new StringContent(json, Encoding.UTF8, "application/json");

        var processResult = await client.PostAsync(uriToServer, httpContent);
        var responseBody = processResult.Content.ReadAsStringAsync().Result;

        Console.WriteLine(responseBody);
        //return JsonConvert.DeserializeObject<string>(responseBody);
    }
}

我在谷歌上搜索并找到了一个“HttpClientHandler.ClientCertificates.Add”,但那是针对 .Net Core 而不是 4.5。
这是否适用于 HttpClient,还是我必须使用 HttpWebRequest 类?
更新:
相关的答案来自“Peter Bons”(再次感谢),由于使用仅为 try-finally,因此我将代码更改为:
// Create an WebRequestHandler instance
var handler = new WebRequestHandler();

// Add the certificate
var certFile = Path.Combine(pathToWorkingDirectory, "SERVER.PFX");
handler.ClientCertificates.Add(new X509Certificate2(certFile, "password"));

var client = new HttpClient(handler);
try
{
    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var httpContent = new StringContent(json, Encoding.UTF8, "application/json");

    //var processResult = await client.GetAsync("https://server/login");
    var processResult = await client.PostAsync("https://server/p/m", httpContent);
    var responseBody = processResult.Content.ReadAsStringAsync().Result;

    Console.WriteLine(responseBody);
}
catch (Exception e)
{
    Console.WriteLine($"ERROR: {e}");
}
finally
{
    client.Dispose();
}

很不幸,服务器返回了403禁止访问的错误信息...我该如何检查证书授权是否有效?更新2:看起来这个问题的答案在于调试:enter image description here。我测试了密码和错误的证书密码会导致异常。所以我不确定服务器是否接受了证书但是服务器路径已经失效或者服务器不接受证书。更新3:查看响应对象显示更多信息,但无法确定证书是否导致了错误。enter image description here。但内容中有一个异常吗?enter image description here。更新4:
很遗憾,服务器从未收到证书... 最后更新 问题出在我从系统管理员那里获取的证书。代码可以运行。问题解决 :)
1个回答

19

你应该像这个例子中那样使用WebRequestHandler类:

var handler = new WebRequestHandler();

var certFile = Path.Combine(@"d:\temp\", "cert.pfx");
handler.ClientCertificates.Add(new X509Certificate2(certFile, "password"));

using (var client = new HttpClient(handler))
{
    ....
}

查看此链接以获取更多背景信息。


太好了!感谢您的回答。 :-) 我会仔细阅读背景信息并提供反馈。 - user3772108
很不幸,我们的系统管理员告诉我服务器从未收到证书。也许你有时间检查一下我的更新并查看我做错了什么? - user3772108
1
@user3772108 我非常确定我回答中的代码是正确的,但请注意Web服务器可能需要额外的信息。因此,您应该与系统管理员确认服务器已正确配置。请参见https://technet.microsoft.com/en-us/library/5adc0029-8875-4390-a717-e5eb2eba9778。不幸的是,这超出了问题的范围,很难提供帮助。正如您在调试时所看到的,客户端证书正在发送,因此该部分有效。 - Peter Bons
好的,所以调试(截图)是正确的,客户端确实发送了带有证书的请求(POST)?再次感谢您的回答。我会与我们的系统管理员核实。 - user3772108
你是对的!是证书的问题!难以置信... 再次感谢您的大力帮助! :-) - user3772108
关于使用 HttpClient 的注意事项;我们应该保存和重复使用我们的 HttClients,而不是在需要它们时创建新的:https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接