Yesterday I got the task to do a “quick” POC to test a call to a service (without SOAP) using a client certificate. First of all please do not ask why we want to do it without SOAP. That is a very loooong story.
After some initial poking around I found a few good links:
· http://blogs.msdn.com/adarshk/archive/2004/09/01/224214.aspx
o This is adarsh blog and I liked it because it is short and sweet and it put me on the right track. Only ugly part is that this example was for .Net 2.0 beta so the X509CertificateEx class has been renamed to X509Certificate2. It is still in the System.Security.Cryptography.X509Certificates namespace.
· http://support.microsoft.com/kb/895971/en-us
o This article is for .Net 1.0 and 1.1 but have some good tips if you want to see the installed certificates on your machine.
I ended up with a pretty clean solution but are having a weird problem when I run it on the server. I get the following error sometimes and am trying to find a solution for this now (will keep you posted):
The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.
I found some good info here: http://weblogs.asp.net/jan/archive/2004/05/08/128394.aspx. This is for WSE but it has fixed my problem as well.
Here is the current code I am playing with (and it works):
Some important using statements for this to work:
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Security.Policy;
private void SecureTest(){
try{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(“http://myurl/TestService”);
req.Method = "POST";
req.KeepAlive = false;
X509Certificate2 Cert = new X509Certificate2();
string CertPath = “c:\temp\cert.p12”;
string CertPwd = “certpassword”;
Cert.Import(CertPath, CertPwd, X509KeyStorageFlags.PersistKeySet);
req.ClientCertificates.Add(Cert);
Stream s = req.GetRequestStream();
StreamWriter sw = new StreamWriter(s);
sw.Write(txtInput.Text);
sw.Close();
s.Close();
// submit synchronous HTTP request to Web server
WebResponse rsp = req.GetResponse();
// WebResponse provides stream-based access so let's go get it baby
StreamReader sr = new StreamReader(rsp.GetResponseStream());
txtSecureOutput.Text = sr.ReadToEnd();
}
catch (Exception ex) { throw ex; }
}