使用证书身份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; }