带有客户端证书的 HttpWebRequest 总是收到错误 "The request was aborted: Could not create SSL/TLS secure channel."

HttpWebRequest with client certificate always getting the error "The request was aborted: Could not create SSL/TLS secure channel."

我正在使用 C# HttpWebRequest 向通过客户端证书进行身份验证的 Web 服务发送 XML 请求(该证书已由 public 机构提供,并且有效且已正确安装在服务器中证书存储)。

这是我的代码:

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

当代码在 webRequest.GetRequestStream() 行输入方法 InsertSoapEnvelopeIntoWebRequest 时,我总是检索错误 "The request was aborted: Could not create SSL/TLS secure channel."。 有人有想法帮助我吗?

我刚刚解决了一个非常相似的问题。在我的例子中,只要我们将客户端证书附加到 WebRequestHandler,我们就会收到 "The request was aborted: Could not create SSL/TLS secure channel." 错误。

在这种情况下,解决方案是授予 IIS_IUSRS 用户组读取客户端证书私钥的权限。一旦完成,错误就消失了。

您可以在 mmc 的证书管理单元中执行此操作。在适当的商店中找到客户端证书,右键单击它 -> 所有任务 -> 管理私钥 -> 添加执行您进程的用户或用户组(如果您在 IIS 上 运行,则 IIS_IUSRS 有效) 并确保它具有 "Read" 权限。