C# ssl时如何忽略证书检查
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12506575/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to ignore the certificate check when ssl
提问by Joe.wang
I am trying find a way to ignore the certificate check when request a Https resource, so far, I found some helpful article in internet.
我正在尝试找到一种在请求 Https 资源时忽略证书检查的方法,到目前为止,我在互联网上找到了一些有用的文章。
But I still have some problem. Please review my code. I just don't understand what does the code ServicePointManager.ServerCertificateValidationCallbackmean.
但我仍然有一些问题。请检查我的代码。我只是不明白代码ServicePointManager.ServerCertificateValidationCallback是什么意思。
When will this delegate method be called? And one more question, in which place should I write this code? Before ServicePointManager.ServerCertificateValidationCallbackexecute or before Stream stream = request.GetRequestStream()?
什么时候会调用这个委托方法?还有一个问题,我应该在哪个地方写这段代码?在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;
}
}
采纳答案by Sani Singh Huttunen
Since there is only one global ServicePointManager, setting ServicePointManager.ServerCertificateValidationCallbackwill yield the result that all subsequent requests will inherit this policy. Since it is a global "setting" it would be prefered to set it in the Application_Startmethod in Global.asax.
由于只有一个全局ServicePointManager,因此设置ServicePointManager.ServerCertificateValidationCallback将产生所有后续请求都将继承此策略的结果。由于它是一个全局“设置”,因此最好在Global.asax的Application_Start方法中设置它。
Setting the callback overrides the default behaviour and you can yourself create a custom validation routine.
设置回调会覆盖默认行为,您可以自己创建自定义验证例程。
回答by blak3r
This worked for me:
这对我有用:
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
};
Snippet from here: http://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors
来自这里的片段:http: //www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors
回答by MCattle
Adding to Sani's and blak3r's answers, I've added the following to the startup code for my application, but in VB:
添加到 Sani 和 blak3r 的答案中,我已将以下内容添加到我的应用程序的启动代码中,但在 VB 中:
'** Overriding the certificate validation check.
Net.ServicePointManager.ServerCertificateValidationCallback = Function(sender, certificate, chain, sslPolicyErrors) True
Seems to do the trick.
似乎可以解决问题。
回答by Adam Venezia
For anyone interested in applying this solution on a per request basis, this is an option and uses a Lambda expression. The same Lambda expression can be applied to the global filter mentioned by blak3r as well. This method appears to require .NET 4.5.
对于有兴趣在每个请求的基础上应用此解决方案的任何人,这是一个选项并使用 Lambda 表达式。同样的 Lambda 表达式也可以应用于 blak3r 提到的全局过滤器。此方法似乎需要 .NET 4.5。
String url = "https://www.stackoverflow.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
In .NET 4.0, the Lambda Expression can be applied to the global filter as such
在 .NET 4.0 中,Lambda 表达式可以应用于全局过滤器
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
回答by Jesse Chisholm
Mention has been made that before .NET 4.5 the property on the request to access its ServicePointManagerwas not available.
已经提到在 .NET 4.5 之前,请求访问它的属性ServicePointManager不可用。
Here is .NET 4.0 code that will give you access to the ServicePointon a per-request basis. It doesn't give you access to the per-request callback, but it should let you find out more details about the problem. Just access the scvPoint.Certificate(or ClientCertificateif you prefer) properties.
这是 .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());
}
回答by Andrej Grobler
Based on Adam's answer and Rob's comment I used this:
根据亚当的回答和罗布的评论,我使用了这个:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => certificate.Issuer == "CN=localhost";
which filters the "ignoring" somewhat. Other issuers can be added as required of course. This was tested in .NET 2.0 as we need to support some legacy code.
这在某种程度上过滤了“忽略”。当然可以根据需要添加其他发行人。这是在 .NET 2.0 中测试的,因为我们需要支持一些遗留代码。
回答by Andrej Rommel
Also there is the short delegate solution:
还有一个简短的委托解决方案:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
回答by Melbourne Developer
Just incidentally, this is a the least verbose way of turning off all certificate validation in a given app that I know of:
顺便说一句,这是我所知道的在给定应用程序中关闭所有证书验证的最简单的方法:
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
回答by Simon_Weaver
Tip:You can also use this method to track certificates that are due to expire soon. This can save your bacon if you discover a cert that is about to expire and can get it fixed in time. Good also for third party companies - for us this is DHL / FedEx. DHL just let a cert expire which is screwing us up 3 days before Thanksgiving. Fortunately I'm around to fix it ... this time!
提示:您还可以使用此方法来跟踪即将到期的证书。如果您发现证书即将过期并且可以及时修复,这可以节省您的培根。对第三方公司也有好处——对我们来说,这就是 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;
}
}
}
回答by Osa E
Several answers above work. I wanted an approach that I did not have to keep making code changes and did not make my code unsecure. Hence I created a whitelist. Whitelist can be maintained in any datastore. I used config file since it is a very small list.
上面的几个答案都有效。我想要一种方法,我不必不断更改代码并且不会使我的代码不安全。因此我创建了一个白名单。白名单可以在任何数据存储中维护。我使用了配置文件,因为它是一个非常小的列表。
My code is below.
我的代码如下。
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => {
return error == System.Net.Security.SslPolicyErrors.None || certificateWhitelist.Contains(cert.GetCertHashString());
};

