我正在使用 C# HttpWebRequest 向通过客户端证书进行身份验证的 Web 服务发送 XML 请求(该证书已由公共机构提供,并且有效且正确安装在服务器证书存储中)。
这是我的代码:
public void CallWebService()
{
var _url = webServiceUrl;
var _action = "soapActionToCall";
X509Certificate2 Cert = null;
try
{
//Search for the certificate in the store
X509Store Store = new X509Store(StoreName.Root);
Store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection Coll = Store.Certificates.Find(X509FindType.FindBySubjectName, "certifcateCommonName", false);
if (Coll != null && Coll.Count > 0)
{
Cert = Coll[0];
}
else
throw new Exception("Certificate non found!");
//Method to create the soap XML envelope
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(typeOfService);
HttpWebRequest webRequest = CreateWebRequest(_url, _action, soapEnvelopeXml.InnerText.Length);
webRequest.ClientCertificates.Add(Cert);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
//Display the XML result
txtResponse.Text = soapResult;
}
}
catch (WebException webEx)
{
WebResponse errResp = webEx.Response;
string text = "";
XmlDocument xmlRsp = null;
string error = "";
if (errResp != null)
{
using (Stream respStream = errResp.GetResponseStream())
{
StreamReader reader = new StreamReader(respStream);
text = reader.ReadToEnd();
}
xmlRsp = new XmlDocument();
xmlRsp.LoadXml(text);
if (xmlRsp.GetElementsByTagName("soapenv:Fault").Count > 0)
error = xmlRsp.SelectSingleNode("//error").InnerText;
if (error.Length > 0)
throw new Exception(error);
else
throw webEx;
}
else
throw webEx;
}
}
private HttpWebRequest CreateWebRequest(string url, string action, int contentLength)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.Host = "host";
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.ContentLength = contentLength;
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
ServicePointManager.Expect100Continue = true;
// { Ssl3 = 48, Tls = 192, Tls11 = 768, Tls12 = 3072, } }.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
// allows for validation of SSL conversations
ServicePointManager.ServerCertificateValidationCallback = delegate(
Object obj, X509Certificate certificate, X509Chain chain,
SslPolicyErrors errors)
{
return (true);
};
return webRequest;
}
private XmlDocument CreateSoapEnvelope()
{
XmlDocument soapEnvelop = new XmlDocument();
soapEnvelop.Load("XmlFileToSend.xml");
return soapEnvelop;
}
private void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
我总是检索错误“请求已中止:无法创建 SSL/TLS 安全通道。” 当代码在 webRequest.GetRequestStream() 行输入方法 InsertSoapEnvelopeIntoWebRequest 时。有人有想法可以帮助我吗?
我刚刚解决了一个非常类似的问题。就我而言,一旦我们将客户端证书附加到 WebRequestHandler,我们就会收到“请求已中止:无法创建 SSL/TLS 安全通道”。错误。
在这种情况下,解决方案是授予 IIS_IUSRS 用户组读取客户端证书私钥的权限。一旦完成,错误就消失了。
您可以在 mmc 中的证书管理单元中执行此操作。在适当的存储中找到客户端证书,右键单击它 -> 所有任务 -> 管理私钥 -> 添加执行您的进程的用户或用户组(如果您在 IIS 上运行,则 IIS_IUSRS 有效)并确保它具有“阅读”权限。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句