Ssl 时如何忽略证书检查

我试图找到一种方法来忽略证书检查时请求一个 Https 资源,到目前为止,我发现了一些有用的文章在互联网上。

但我仍然有一些问题。请检查我的代码。我只是不明白代码 ServicePointManager.ServerCertificateValidationCallback是什么意思。

何时调用此委托方法?还有一个问题,我应该在哪里写代码?在 ServicePointManager.ServerCertificateValidationCallback执行之前还是在 Stream stream = request.GetRequestStream()执行之前?

public HttpWebRequest GetRequest()
{
CookieContainer cookieContainer = new CookieContainer();


// Create a request to the server
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_remoteUrl);


#region Set request parameters


request.Method = _context.Request.HttpMethod;
request.UserAgent = _context.Request.UserAgent;
request.KeepAlive = true;
request.CookieContainer = cookieContainer;
request.PreAuthenticate = true;
request.AllowAutoRedirect = false;


#endregion


// For POST, write the post data extracted from the incoming request
if (request.Method == "POST")
{
Stream clientStream = _context.Request.InputStream;
request.ContentType = _context.Request.ContentType;
request.ContentLength = clientStream.Length;


ServicePointManager.ServerCertificateValidationCallback = delegate(
Object obj, X509Certificate certificate, X509Chain chain,
SslPolicyErrors errors)
{
return (true);
};


Stream stream = request.GetRequestStream();


....
}


....


return request;
}
}
349705 次浏览

由于只有一个全局 ServicePointManager,因此设置 回调将产生所有后续请求都将继承此策略的结果。因为它是一个全局“设置”,所以最好在 Global.asax应用程序 _ 开始方法中设置它。

设置回调会覆盖默认行为,您可以自己创建一个自定义验证例程。

这对我很有效:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true; // **** Always accept
};

片段来自这里: http://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors

为了给 Sani 和 blak3r 添加答案,我在我的应用程序的启动代码中添加了以下代码,但是在 VB 中:

'** Overriding the certificate validation check.
Net.ServicePointManager.ServerCertificateValidationCallback = Function(sender, certificate, chain, sslPolicyErrors) True

看起来很管用。

对于有兴趣在每个请求基础上应用此解决方案的任何人来说,这是一个选项,并使用 Lambda 表达式。相同的 Lambda 表达式也可以应用于 blak3r 提到的全局过滤器。此方法似乎需要。NET 4.5.

String url = "https://www.stackoverflow.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

在.NET 4.0中,Lambda 表达式可以应用于全局过滤器

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

有人提到,在.NET 4.5之前,访问其 ServicePointManager请求的属性是不可用的。

给你。NET 4.0代码,可以根据每个请求访问 ServicePoint。它不允许您访问每个请求的回调,但是它应该允许您查找有关问题的更多细节。只需访问 scvPoint.Certificate(或者 ClientCertificate,如果您愿意)属性。

WebRequest request = WebRequest.Create(uri);


// oddity: these two .Address values are not necessarily the same!
//  The service point appears to be related to the .Host, not the Uri itself.
//  So, check the .Host vlaues before fussing in the debugger.
//
ServicePoint svcPoint = ServicePointManager.FindServicePoint(uri);
if (null != svcPoint)
{
if (!request.RequestUri.Host.Equals(svcPoint.Address.Host, StringComparison.OrdinalIgnoreCase))
{
Debug.WriteLine(".Address              == " + request.RequestUri.ToString());
Debug.WriteLine(".ServicePoint.Address == " + svcPoint.Address.ToString());
}
Debug.WriteLine(".IssuerName           == " + svcPoint.Certificate.GetIssuerName());
}

基于亚当的回答和罗伯的评论,我这样写道:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => certificate.Issuer == "CN=localhost";

当然,也可以根据需要增加其他发行人。 这是在.NET 2.0中测试的,因为我们需要支持一些遗留代码。

此外,还有一种简短的委托解决方案:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

顺便说一句,这是我所知道的关闭给定应用程序中所有证书验证的最简单的方法:

ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;

提示: 您还可以使用此方法跟踪即将过期的证书。这可以节省你的培根,如果你发现一个证书即将过期,可以得到它及时修复。对第三方公司也有好处——对我们来说,这是 DHL/FedEx。DHL 刚刚让一张证书过期了,这让我们在感恩节前三天搞砸了。幸运的是,这次我能修好它!

    private static DateTime? _nextCertWarning;
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
{
if (error == SslPolicyErrors.None)
{
var cert2 = cert as X509Certificate2;
if (cert2 != null)
{
// If cert expires within 2 days send an alert every 2 hours
if (cert2.NotAfter.AddDays(-2) < DateTime.Now)
{
if (_nextCertWarning == null || _nextCertWarning < DateTime.Now)
{
_nextCertWarning = DateTime.Now.AddHours(2);


ProwlUtil.StepReached("CERT EXPIRING WITHIN 2 DAYS " + cert, cert.GetCertHashString());   // this is my own function
}
}
}


return true;
}
else
{
switch (cert.GetCertHashString())
{
// Machine certs - SELF SIGNED
case "066CF9CAD814DE2097D367F22D3A7E398B87C4D6":


return true;


default:
ProwlUtil.StepReached("UNTRUSTED CERT " + cert, cert.GetCertHashString());
return false;
}
}
}

上述工作的几个答案。我想要一种方法,我不必一直做代码更改,也不会使我的代码不安全。因此我创建了一个白名单。白名单可以在任何数据存储中维护。我使用配置文件,因为它是一个非常小的列表。

我的代码在下面。

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => {
return error == System.Net.Security.SslPolicyErrors.None || certificateWhitelist.Contains(cert.GetCertHashString());
};

您可以在 HttpClient 的本地实例上设置回调,而不必向 ServicePointManager 添加回调,这将覆盖全局的证书验证。此方法应该只影响使用 HttpClient 实例进行的调用。

下面的示例代码展示了如何在 Web API 控制器中实现忽略特定服务器的证书验证错误。

using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;


public class MyController : ApiController
{


// use this HttpClient instance when making calls that need cert errors suppressed
private static readonly HttpClient httpClient;


static MyController()
{
// create a separate handler for use in this controller
var handler = new HttpClientHandler();


// add a custom certificate validation callback to the handler
handler.ServerCertificateCustomValidationCallback = ((sender, cert, chain, errors) => ValidateCert(sender, cert, chain, errors));


// create an HttpClient that will use the handler
httpClient = new HttpClient(handler);
}


protected static ValidateCert(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
{


// set a list of servers for which cert validation errors will be ignored
var overrideCerts = new string[]
{
"myproblemserver",
"someotherserver",
"localhost"
};


// if the server is in the override list, then ignore any validation errors
var serverName = cert.Subject.ToLower();
if (overrideCerts.Any(overrideName => serverName.Contains(overrideName))) return true;


// otherwise use the standard validation results
return errors == SslPolicyErrors.None;
}


}

明确表示..。

ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(CertCheck);


private static bool CertCheck(object sender, X509Certificate cert,
X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}

脆弱性分析工具将提醒您注意这些代码。

密码正确:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =>
{
return (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.RemoteCertificateNotAvailable;
};

Unity C # 这个解决方案的版本:

void Awake()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback += ValidateCertification;
}


void OnDestroy()
{
ServerCertificateValidationCallback = null;
}


public static bool ValidateCertification(object sender, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true;
}

对于.net 核心

using (var handler = new HttpClientHandler())
{
// allow the bad certificate
handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => true;
using (var httpClient = new HttpClient(handler))
{
await httpClient.PostAsync("the_url", null);
}
}

在.NetCore 3.1上,可以通过声明自定义验证方法来解决这个问题。

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
  

因此,在发出请求之前,声明这个回调方法

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://someurl.com/service/");
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
  

这样,验证将始终通过,因为您的自定义方法始终返回 true值。