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

时间:2018-12-03 23:38:04

标签: ssl ssl-certificate dotnet-httpclient

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

标题为:

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

正文(x-www-form-urlencoded)

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

当我通过.NET执行类似请求时,我收到一条错误代码,指示不存在证书。我已将证书添加到我的个人证书存储中并进行了验证 证书已通过调试添加到Web处理程序中。 任何人都可以建议错误可能是什么或如何诊断问题?

    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 个答案:

答案 0 :(得分:0)

最后找到了答案–问题是未加载私钥文件。邮递员成功发送了请求,Curl也成功发送了请求。 Curl要求显式地提供密钥文件,这是一个线索。

.NET Core中-X509Certificate2对象上有一个功能,可让您将其复制到与密钥文件组合在一起的另一个对象中。我的项目在.NET Framework中,而Core无法使用。

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