强制HttpWebRequest发送客户端证书 [英] Force HttpWebRequest to send client certificate
问题描述
我有一个p12证书,我以这种方式加载它:
I have a p12 certificate, that I load it in this way:
X509Certificate2 certificate = new X509Certificate2(certName, password,
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
它已正确加载,实际上如果我做 certificate.PrivateKey.ToXmlString (true);
它返回一个完整的xml,且没有错误。
但如果我这样做:
It is loaded correcty, in fact If i do certificate.PrivateKey.ToXmlString(true);
it returns a complete xml without errors.
But If I do:
try
{
X509Chain chain = new X509Chain();
var chainBuilt = chain.Build(certificate);
Console.WriteLine("Chain building status: "+ chainBuilt);
if (chainBuilt == false)
foreach (X509ChainStatus chainStatus in chain.ChainStatus)
Console.WriteLine("Chain error: "+ chainStatus.Status);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
它写道:
Chain building status: False
Chain error: RevocationStatusUnknown
Chain error: OfflineRevocation
所以当我这样做时:
ServicePointManager.CheckCertificateRevocationList = false;
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
ServicePointManager.Expect100Continue = true;
Console.WriteLine("connessione a:" + host);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
req.PreAuthenticate = true;
req.AllowAutoRedirect = true;
req.ClientCertificates.Add(certificate);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
string postData = "login-form-type=cert";
byte[] postBytes = Encoding.UTF8.GetBytes(postData);
req.ContentLength = postBytes.Length;
Stream postStream = req.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();
WebResponse resp = req.GetResponse();
服务器说证书未发送/有效。
the server says that the certificate is not sent/valid.
我的问题是:
- 即使链构建为假,如何发送证书?
- 还有另一个类来发布证书,该类在发送证书之前不会检查证书的有效性?
非常感谢。
Antonino
many thanks. Antonino
推荐答案
我解决了这个问题,关键是P12文件(作为PFX)包含更多1个证书,因此必须以这种方式加载:
I resolved the problem, The point is that a P12 file (as a PFX) contains more then 1 certificate, so it must be loaded in this way:
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
并以这种方式添加到HttpWebRequest中: request.ClientCertificates = certificate;
and added to a HttpWebRequest in this way: request.ClientCertificates = certificates;
感谢大家的支持。
完整的示例代码
string host = @"https://localhost/";
string certName = @"C:\temp\cert.pfx";
string password = @"password";
try
{
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
req.AllowAutoRedirect = true;
req.ClientCertificates = certificates;
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
string postData = "login-form-type=cert";
byte[] postBytes = Encoding.UTF8.GetBytes(postData);
req.ContentLength = postBytes.Length;
Stream postStream = req.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();
WebResponse resp = req.GetResponse();
Stream stream = resp.GetResponseStream();
using (StreamReader reader = new StreamReader(stream))
{
string line = reader.ReadLine();
while (line != null)
{
Console.WriteLine(line);
line = reader.ReadLine();
}
}
stream.Close();
}
catch(Exception e)
{
Console.WriteLine(e);
}
这篇关于强制HttpWebRequest发送客户端证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!