使用证书身份validation访问Web服务和HTTP接口

这是我第一次使用证书身份validation。 商业合作伙伴公开两种服务,XML Web服务和HTTP服务。 我必须使用.NET客户端访问它们。

我试过的

0.设置环境

我已使用certmgr.exe在本地计算机(win 7 professional)中安装了SSLCACertificates(在root和两个中间)和客户端证书。

1.对于Web服务

  • 我有客户证书(der)。
  • 该服务将通过.NET代理使用。

这是代码:

OrderWSService proxy = new OrderWSService(); string CertFile = "ClientCert_DER.cer"; proxy.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(CertFile)); orderTrackingTO ot = new orderTrackingTO() { order_id = "80", tracking_id = "82", status = stateOrderType.IN_PREPARATION }; resultResponseTO res = proxy.insertOrderTracking(ot); 

最后一条语句报告的exception: The request failed with an empty response

2.对于HTTP接口

  • 它是我必须通过POST方法调用的HTTPS接口。
  • HTTPS请求将使用HTTPWebRequest从.NET客户端发送。

这是代码:

 string PostData = "MyPostData"; //setting the request HttpWebRequest req; req = (HttpWebRequest)HttpWebRequest.Create(url); req.UserAgent = "MyUserAgent"; req.Method = "POST"; req.ContentType = "application/x-www-form-urlencoded"; req.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(CertFile, "MyPassword")); //setting the request content byte[] byteArray = Encoding.UTF8.GetBytes(PostData); Stream dataStream = req.GetRequestStream(); dataStream.Write(byteArray, 0, byteArray.Length); dataStream.Close(); //obtaining the response WebResponse res = req.GetResponse(); r = new StreamReader(res.GetResponseStream()); 

最后一条语句报告的exception: The request was aborted: Could not create SSL/TLS secure channel

3.上次尝试:使用浏览器

在Chrome中,安装证书后,如果我尝试访问这两个url,则会收到107错误:

 Error 107 (net::ERR_SSL_PROTOCOL_ERROR) 

我被卡住了。

以下内容可帮助您确定问题,以下是测试SSL连接的两种方法,一种是测试站点,另一种是回调方法,用于确定SSL失败的原因。 如果没有别的东西它应该让你更好地了解它失败的原因。

当调用该方法时,它将弹出选择证书对话框,显然当您真正执行此操作时,您将希望自动从证书库中读取。 我之所以这样做是因为如果找不到有效的证书,那么你就会知道你的问题与证书的安装方式有关。

最好的办法是将此代码放在一个简单的控制台应用程序中:

 using System.Security.Cryptography.X509Certificates; using System.Net.Security; using System.Net; private static void CheckSite(string url, string method) { X509Certificate2 cert = null; ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate; X509Store store = new X509Store(StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2Collection certcollection = (X509Certificate2Collection)store.Certificates; // pick a certificate from the store cert = X509Certificate2UI.SelectFromCollection(certcollection, "Caption", "Message", X509SelectionFlag.SingleSelection)[0]; store.Close(); HttpWebRequest ws = (HttpWebRequest)WebRequest.Create(url); ws.Credentials = CredentialCache.DefaultCredentials; ws.Method = method; if (cert != null) ws.ClientCertificates.Add(cert); using (HttpWebResponse webResponse = (HttpWebResponse)ws.GetResponse()) { using (Stream responseStream = webResponse.GetResponseStream()) { using (StreamReader responseStreamReader = new StreamReader(responseStream, true)) { string response = responseStreamReader.ReadToEnd(); Console.WriteLine(response); responseStreamReader.Close(); } responseStream.Close(); } webResponse.Close(); } } ///  /// Certificate validation callback. ///  private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) { // If the certificate is a valid, signed certificate, return true. if (error == System.Net.Security.SslPolicyErrors.None) { return true; } Console.WriteLine("X509Certificate [{0}] Policy Error: '{1}'", cert.Subject, error.ToString()); return false; }