Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 views
in Technique[技术] by (71.8m points)

c# - Accessing a web service and a HTTP interface using certificate authentication

It is the first time I have to use certificate authentication. A commercial partner expose two services, a XML Web Service and a HTTP service. I have to access both of them with .NET clients.

What I have tried

0. Setting up the environment

I have installed the SSLCACertificates (on root and two intermediate) and the client certificate in my local machine (win 7 professional) using certmgr.exe.

1. For the web service

  • I have the client certificate (der).
  • The service will be consumed via a .NET proxy.

Here's the code:

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 reported at last statement: The request failed with an empty response.

2. For the HTTP interface

  • it is a HTTPS interface I have to call through POST method.
  • The HTTPS request will be send from a .NET client using HTTPWebRequest.

Here's the code:

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 reported at last statement: The request was aborted: Could not create SSL/TLS secure channel.

3. Last try: using the browser

In Chrome, after installing the certificates, if I try to access both urls I get a 107 error:

Error 107 (net::ERR_SSL_PROTOCOL_ERROR)

I am stuck.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The following should help you identify the issue, here are two methods to test SSL connectivity one tests the site whilst the other is a callback method to identify why SSL failed. If nothing else it should give you a better idea why it is failing.

When the method is called it will pop up with the select certificate dialog box, obviously when you do this for real you'll want to read from the cert store automatically. The reason I have put this in is because if no valid certificate is found then you will know your problem is with the way the certificate is installed.

The best thing to do is put this code in a simple console app:

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...