2013-03-22 93 views
5

要忽略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; }; 
    }  
} 
  1. 将这个代码是线程安全的? msdn上的文档说任何类型的ServicePointManager静态成员都是线程安全的,但我只是想确认一下。 http://msdn.microsoft.com/en-us/library/zkfa48de%28v=vs.80%29.aspx
  2. finally块中的代码是将其重置为默认值的正确方法吗?
+1

不,这不会是 “线程安全的”。回调可以随时通过任何其他线程进行更改。 – 2013-03-22 20:02:18

+1

顺便说一句,就静态成员而言,“线程安全”仅仅意味着这些成员自动修改静态(如果有的话)。修改'ServerCertificateValidationCallback'的两个线程在这方面是“线程安全的”。但是,从应用程序的角度来看,这不是线程安全的,因为一个线程的数据(*它*'ServerCertificateValidationCallback'值)可能被另一个线程覆盖 - 可能导致线程中的代码出现故障。在无法控制的线程中,无法同步对“ServerCertificateValidationCallback”的访问。 – 2013-03-22 20:12:11

+0

谢谢彼得的回复。我在他们提出这种技术的地方看到了很多帖子,但显然它不起作用。我不确定忽略内部Web请求的SSL证书错误的最佳方法是什么。 – user1689030 2013-03-25 20:36:47

回答

5

如果你需要重写默认证书验证,请考虑以下的一种或多种:

  1. ServerCertificateValidationCallback一次且仅一次 - 应用在启动期间或可能在静态构造函数。这消除了线程争用的风险。
  2. 既然你让安全更加宽容,限制行为调试版本与条件编译:

    #if DEBUG 
        ServicePointManager.ServerCertificateValidationCallback += Callback; 
    #endif 
    
  3. 最后,请记住您的委托是一个丰富的功能。您不必简单地返回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); 
        } 
    }