我需要实现一个检查Web服务是否可用的方法。
主要问题是网址为HTTPS,需要证书。
所以我需要从机器上获取证书,然后创建HttpWebRequest
以获得HttpWebResponse
。
通过我的实际实现,我可以检索证书,但是当我调用request.GetResponse()
方法时,它会抛出此异常:
[System.Net.WebException] = {"底层连接已关闭:发送时出现意外错误"}
的InnerException:
[System.IO.IOException] = {"收到意外的EOF或0字节 传输流"}
我阅读了许多可能的解决方案,但似乎没有一个对我有用。 我在 .NET 3.5 。
这是我的代码
using (WebClient client = new WebClient())
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, CertificateThumbprint, false);
if (certificates.Count == 0)
throw new Exception("No corresponding certificate found.");
X509Certificate2 certificate = certificates[0];
// Not compiling on .NET 3.5
// Error: cannot apply '+=' operator to
//'System.Net.Security.RemoteCertificateValidationCallback'
//and 'anonymous method'
//ServicePointManager.ServerCertificateValidationCallback +=
// delegate(
// object sender,
// X509Certificate certificate,
// X509Chain chain,
// SslPolicyErrors sslPolicyErrors)
// {
// return true;
// };
// Not compiling on .NET 3.5
// Error: cannot apply '+=' operator to 'System.Net.Security.RemoteCertificateValidationCallback' and 'lambda expression'
// ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
// Not working
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
// Not working
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(UrlWSInvioComunicazioni);
request.ClientCertificates.Add(certificate);
request.Method = "HEAD";
// throws Exception...
HttpWebResponse webResponse = request.GetResponse() as HttpWebResponse;
webResponse.Close();
response.ResultCode = ResultCode.Success;
response.ResultMessage = "Service available.";
}
更新2017/05/10
由于我在.NET 3.5上不支持TLS 1.2,我使用了Microsoft的补丁(参见KB3154519),可以使用TLS 1.2 SecurityProtocolTypeExtensions
和SslProtocolsExtensions
个扩展程序。
自2017年1月(微软发布补丁程序)以来,我已经将这种方法与其他一些Web服务一起使用了,它的运行没有任何问题。
我认为我现在遇到的问题是:
[System.Net.WebException] = {"请求已中止:无法创建SSL / TLS安全通道。"}
与我的电脑中的某些东西有关。
更新2017/05/12
我终于发现问题是与IIS相关。我的PC上的Web应用程序的应用程序池运行时标识设置为ApplicationPoolIdentity
。设置为LocalSystem
或我当前的用户(管理员)时,它可以正常工作。
因此,当应用程序池以ApplicationPoolIdentity运行时,我认为访问证书的内容不正确。
答案 0 :(得分:1)
扫描URL以查看服务器正在使用的SSL提供程序。你可以在这里做到 - > https://www.ssllabs.com/ssltest/analyze.html
出于安全原因,某些服务器已禁用ssl3。所以你必须改用这个设置:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
或使用Tls 1.2,如果客户端可用。
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls12;
<强>更新强> 检查此代码是否适合您
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | (SecurityProtocolType)3072;
var httpRequest = (HttpWebRequest)WebRequest.Create("https://google.com");
httpRequest.Method = "GET";
httpRequest.ContentType = "text/html";
httpRequest.KeepAlive = false;
httpRequest.MaximumAutomaticRedirections = 30;
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
var responseStream = new StreamReader(httpResponse.GetResponseStream());
var strResponse = responseStream.ReadToEnd();
httpResponse.Close();
responseStream.Close();