我正在编写测试以测试我正在部署的服务,绕过ssl证书检查我使用下面的代码段实现了ssl覆盖:
public static void SSLValidationOverride()
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnValidationCallback);
}
private static bool OnValidationCallback(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
{
if (cert.subject == MyCertSubject)
return true;
else
return false;
}
现在我必须在代码中使用ssl调用另一个web服务,并希望在调用之前切换到默认的ssl检查。什么是最好的方法。 MS帮助说ServicePointManager.SecurityProtocol的默认值为null(http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.securityprotocol.aspx)。将它设置为null会切换到默认的ssl验证,还有其他方法可以做到这一点。
答案 0 :(得分:6)
在开发我创建的诊断工具期间,我遇到了类似的问题。我创建了一个Windows服务,它向URL列表发出请求。对于每个网址,我通过设置此项来提出没有证书验证的请求:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
然后使用相同的url我还尝试通过将属性重置为null来提出具有证书验证的请求,该属性应该提供默认功能:
ServicePointManager.ServerCertificateValidationCallback = null;
这有意想不到的结果,因为我的请求仍未在没有证书验证的情况下进行,就像忽略了重置一样。经过调试后,我发现如果我在设置
后等待足够长的时间ServicePointManager.ServerCertificateValidationCallback = null;
然后它实际上被重置,我的请求是使用默认证书验证。所以我在提出请求之前只是睡了30秒:
ServicePointManager.ServerCertificateValidationCallback = null;
System.Threading.Thread.Sleep(30000);
//Make request here
我不明白为什么会这样,但确实有更好的方法,如果你知道怎么做,请告诉我。
答案 1 :(得分:2)
我最终将ServicePointManager.SecurityProtocol设置为null,它工作正常。虽然我仍然愿意接受更好的方法来做到这一点
public static void SSLValidationRestore()
{
ServicePointManager.ServerCertificateValidationCallback = null;
}
答案 2 :(得分:2)
将回调设置为null不起作用。相反,所有证书都通过。我不明白为什么这么多人发布了将值设置为null works或 - = works。这项工作也没有......至少在3.5。经过进一步测试后,似乎只是缓存了支票。证书验证一次后重新检查不会导致回调被调用。
答案 3 :(得分:1)
我遇到了类似的问题。您可以将ServicePointManager.MaxServicePointIdleTime更改为较低的值,而不是在@Acode Monkey解决方案上调用Thread.Sleep()。
http://codepen.io/ajkochanowicz/pen/KHdih
答案 4 :(得分:0)
将回调设置为null可以,但是已经建立的连接仍在使用。因此,按照@Acode Monkey的说明,大约30秒内不会检查它们的证书。
有一种方法可以告诉用户不要使用连接太长时间-如@Kyibe答案中所述。但是对我来说,它不适用于100%的情况。
所以我写了一个小助手,谁帮我做这一切:
internal static class ServiceHelper
{
/// <summary>
/// Gets or sets whether to ignore certificate errors.
/// </summary>
public static bool IgnoreCertificateErrors
{
get => _ignoreCertificateErrors;
set => _ignoreCertificateErrors = value;
}
/// <summary>
/// Gets or sets whether to ignore certificate errors.
/// This property is static because it controls the ServicePointManager settings, and that is static.
/// </summary>
private static volatile bool _ignoreCertificateErrors = true;
/// <summary>
/// Callback for certificate validation event, which based on <see cref="_ignoreCertificateErrors"/> will let invalid certificates pass or not.
/// </summary>
private static bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
{
if (_ignoreCertificateErrors)
return true;
// default behavior
return sslpolicyerrors == SslPolicyErrors.None;
}
/// <summary>
/// Calling this method will ensure that certificate validation will be covered by <see cref="IgnoreCertificateErrors" /> property.
/// </summary>
public static void EnsureCustomCertificateValidation()
{
var callbackCount = ServicePointManager.ServerCertificateValidationCallback?.GetInvocationList().Length ?? 0;
// adding callback only if there is no callback already
if (callbackCount == 0)
{
// due to this setting will connection stay active no longer than 1s (so method ValidateCertificate will be called for every action if they are at least 1 second split)
ServicePointManager.MaxServicePointIdleTime = 1000; //ms
// setting the certificate validaction callback
ServicePointManager.ServerCertificateValidationCallback += ValidateCertificate;
}
}
}
然后在使用任何WebService或任何其他方法之前,只需调用ServiceHelper.EnsureCustomCertificateValidation()
。
然后,您可以轻松地在忽略证书错误和默认行为之间切换