多线程设置ServicePointManager.ServerCertificateValidationCallback安全吗?
问题描述:
要忽略ssl证书错误,我在制作HttpWebRequest
之前以静态方法设置ServicePointManager.ServerCertificateValidationCallback
。我只希望完成内部请求,因此我将该属性重置为finally
块中的默认值。但是因为它是一个Web应用程序,当多个线程修改属性时会有问题吗?多线程设置ServicePointManager.ServerCertificateValidationCallback安全吗?
这里是我如何使用属性
public static String GetResource()
{
try
{
ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
}
catch()
{
}
finally
{
ServicePointManager.ServerCertificateValidationCallback -= delegate { return false; };
}
}
- 将这个代码是线程安全的? msdn上的文档说任何类型的ServicePointManager静态成员都是线程安全的,但我只是想确认一下。 http://msdn.microsoft.com/en-us/library/zkfa48de%28v=vs.80%29.aspx
- finally块中的代码是将其重置为默认值的正确方法吗?
答
如果你需要重写默认证书验证,请考虑以下的一种或多种:
- 集
ServerCertificateValidationCallback
一次且仅一次 - 应用在启动期间或可能在静态构造函数。这消除了线程争用的风险。 -
既然你让安全更加宽容,限制行为调试版本与条件编译:
#if DEBUG ServicePointManager.ServerCertificateValidationCallback += Callback; #endif
-
最后,请记住您的委托是一个丰富的功能。您不必简单地返回
true
。您可以询问请求并决定如何处理它。ServicePointManager.ServerCertificateValidationCallback += Callback; static bool Callback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (IsInternalRequest(sender)) { return true; } else { return IsExternalRequestValid(sender, certificate, chain, sslPolicyErrors); } }
不,这不会是 “线程安全的”。回调可以随时通过任何其他线程进行更改。 – 2013-03-22 20:02:18
顺便说一句,就静态成员而言,“线程安全”仅仅意味着这些成员自动修改静态(如果有的话)。修改'ServerCertificateValidationCallback'的两个线程在这方面是“线程安全的”。但是,从应用程序的角度来看,这不是线程安全的,因为一个线程的数据(*它*'ServerCertificateValidationCallback'值)可能被另一个线程覆盖 - 可能导致线程中的代码出现故障。在无法控制的线程中,无法同步对“ServerCertificateValidationCallback”的访问。 – 2013-03-22 20:12:11
谢谢彼得的回复。我在他们提出这种技术的地方看到了很多帖子,但显然它不起作用。我不确定忽略内部Web请求的SSL证书错误的最佳方法是什么。 – user1689030 2013-03-25 20:36:47