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

时间:2012-06-22 09:47:23

标签: c# web-services authentication certificate http-authentication

这是我第一次使用证书身份验证。 商业合作伙伴公开两种服务,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);

最后声明中报告了异常:The request failed with an empty response

2。对于HTTP接口

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

以下是代码:

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());

最后声明中报告了异常:The request was aborted: Could not create SSL/TLS secure channel

第3。上次尝试:使用浏览器

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

Error 107 (net::ERR_SSL_PROTOCOL_ERROR)

我被困住了。

1 个答案:

答案 0 :(得分:5)

以下内容可帮助您确定问题,以下是测试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();
    }
}

/// <summary>
/// Certificate validation callback.
/// </summary>
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;
}