带有客户端证书的 HttpClient POST 请求

Posted

技术标签:

【中文标题】带有客户端证书的 HttpClient POST 请求【英文标题】:HttpClient POST request with Client Certificate 【发布时间】:2018-12-03 23:38:04 【问题描述】:

我正在尝试调用需要客户端证书的第三方 API。我使用 SSL 工具生成了客户端证书,并且 将此上传到第三方网站。我已经通过 Postman 生成了一个成功的 POST 请求,通过提供客户端证书 他们的对话。

标题是:

X-application = (MyApplicationName) Content-Type = application/x-www-form-urlencoded 接受 = 应用程序/json

正文(x-www-form-urlencoded)

用户名 =(用户名) 密码=(密码)

当我通过 .NET 执行类似请求时,我收到一个错误代码,表明证书不存在。我已将证书添加到我的个人证书存储并验证 证书已通过调试添加到 webhandler。 谁能建议错误可能是什么或我如何诊断问题?

    static async void LaunchRawHttpClient()
            
                System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls;
                ServicePointManager.ServerCertificateValidationCallback +=
                    ValidateServerCertificate;


                string page = "https://<URL>";

                var handler = new WebRequestHandler();
                X509Certificate2 cert = GetMyCert();
                if (cert!=  null)
                
                    handler.ClientCertificates.Add(cert);
                
                else
                
                    Console.WriteLine("Cert not found");
                    Console.ReadLine();
                    return;
                


                // ... Use HttpClient.
                using (HttpClient client = new HttpClient(handler))
                
                    client.DefaultRequestHeaders.Add("X-Application", "<applicationname>");
                    client.DefaultRequestHeaders.Add("Accept", "application/json");

                    var nvc = new List<KeyValuePair<string, string>>();
                    nvc.Add(new KeyValuePair<string, string>("username", "<username>"));
                    nvc.Add(new KeyValuePair<string, string>("password", "<password>"));

                    FormUrlEncodedContent reqContent = new FormUrlEncodedContent(nvc);
                    reqContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");


                    using (HttpResponseMessage response = await client.PostAsync(page, reqContent))
                    using (HttpContent content = response.Content)
                    
                        // ... Read the string.
                        string result = await content.ReadAsStringAsync();

                        // ... Display the result.
                        if (result != null)
                        
                            Console.WriteLine(result);
                        
                    
                
            

static X509Certificate2 GetMyCert()
        
            string certThumbprint = "<thumbprint>";
            X509Certificate2 cert = null;

            var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certCollection = store.Certificates.Find
                (X509FindType.FindByThumbprint, certThumbprint, false);

            if (certCollection.Count > 0)
                cert = certCollection[0];

            store.Close();

            return cert;
        
public static bool ValidateServerCertificate(
            object sender,
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
        
            if (sslPolicyErrors == SslPolicyErrors.None)
            
                Console.WriteLine("No SSL Errors");
                return true;
            

            Console.WriteLine("Certificate error: 0", sslPolicyErrors);
            Console.ReadLine();
            return false;
        

我收到“无 SSL 错误”消息 x2,后跟缺少证书状态代码。

提前致谢 吉姆

【问题讨论】:

【参考方案1】:

终于找到了答案——问题是没有加载私钥文件。邮递员成功发送请求,Curl 也是如此。 Curl 明确要求提供密钥文件,这是一个线索。

在 .NET Core 中 - X509Certificate2 对象上有一个函数,可让您将其复制到另一个结合密钥文件的对象。我的项目在 .NET 框架中,Core 不可用。

我选择的选项是使用 openssl 将 cer 和密钥文件组合成一个 pfx,我将其加载到 X509Certificate2 对象中。然后 Http Post 就成功了。

【讨论】:

以上是关于带有客户端证书的 HttpClient POST 请求的主要内容,如果未能解决你的问题,请参考以下文章

通过 Apache Commons HttpClient 发送 HTTPS 请求

HttpClient Post 提交表单数据

C#:带有 POST 参数的 HttpClient

用java做一个httpClient 发送https 的get请求,需要证书验证的那种,求大神指点一下!

HttpClient 拒绝发送自签名客户端证书

带有问题网站的 HTTPclient POST