我正在尝试在请求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;
}
}
答案 0 :(得分:151)
对于有兴趣在每个请求的基础上应用此解决方案的任何人,这是一个选项并使用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 Expression可以像这样应用于全局过滤器
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
答案 1 :(得分:65)
由于只有一个全局ServicePointManager,因此设置ServicePointManager.ServerCertificateValidationCallback将产生所有后续请求将继承此策略的结果。因为它是一个全球性的设置"它最好在Application_Start中的Global.asax方法中进行设置。
设置回调会覆盖默认行为,您可以自己创建自定义验证例程。
答案 2 :(得分:49)
这对我有用:
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
答案 3 :(得分:5)
有人提到在.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());
}
答案 4 :(得分:5)
.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);
}
}
答案 5 :(得分:3)
顺便说一下,这是关闭我所知道的给定应用中所有证书验证的最简洁的方法:
$.ajax
答案 6 :(得分:2)
根据Adam的回答和Rob的评论,我使用了这个:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => certificate.Issuer == "CN=localhost";
在某种程度上过滤了“忽略”。当然,可以根据需要添加其他发行人。 这是在.NET 2.0中测试的,因为我们需要支持一些遗留代码。
答案 7 :(得分:2)
此解决方案的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;
}
答案 8 :(得分:1)
明确表达...
{'BAR': 3, 'BAZ': 3, 'FOO': 3, 'HAM': 3, 'NOM': 1}
答案 9 :(得分:0)
添加到Sani和blak3r的答案,我已将以下内容添加到我的应用程序的启动代码中,但在VB中:
'** Overriding the certificate validation check.
Net.ServicePointManager.ServerCertificateValidationCallback = Function(sender, certificate, chain, sslPolicyErrors) True
似乎可以做到这一点。
答案 10 :(得分:0)
提示:您还可以使用此方法跟踪即将过期的证书。如果您发现即将过期的证书并且可以及时修复它,这可以节省您的培根。也适用于第三方公司 - 对我们来说这是DHL / FedEx。 DHL只是让一个证书到期,这让我们在感恩节前3天搞砸了。幸运的是我现在正在解决这个问题......这次!
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;
}
}
}
答案 11 :(得分:0)
上述工作有几个答案。我想要一种不必不断更改代码且不会使我的代码不安全的方法。因此,我创建了一个白名单。白名单可以在任何数据存储中维护。我使用了配置文件,因为它是一个很小的列表。
我的代码在下面。
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => {
return error == System.Net.Security.SslPolicyErrors.None || certificateWhitelist.Contains(cert.GetCertHashString());
};
答案 12 :(得分:0)
您可以在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;
}
}
答案 13 :(得分:0)
CA5386:漏洞分析工具将提醒您这些代码。
正确的代码:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =>
{
return (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.RemoteCertificateNotAvailable;
};
答案 14 :(得分:0)
在 .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
值。