2011-03-01 98 views
2

我一直在与这个问题争斗超过2个星期,现在已经无处可寻。WebClient.DownloadString()+ REST + HTTPS + Win2003 =挂起线程

首先是环境:Windows 2003 R2 SP2/SharePoint 2007 SP1/.NET 3.5。

基本上,我们正在调用Web服务来从远程API收集数据。 API有几个REST端点和几个SOAP端点。端点是使用摘要身份验证的HTTPS端点。当我们用SOAP端点进行调用时,似乎一切正常。但是接下来我们尝试使用REST进行调用,当IIS确定线程没有响应并且杀死线程时,线程挂起然后死亡。起初,我们认为这是一个SSL问题(它仍然可能是),因为我们在使用HTTP端点(到相同API的路由不是SSL)时看不到任何问题。

下面是我们使用,使REST调用的代码:

private void Process(HttpContext context, String url, String restParam) 
{ 
    ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(validateCertificate); 

    WriteLogMessage("Start Process"); 
    String pattern = "{0}{1}"; 
    String address = String.Format(pattern, url, restParam); 

    WriteLogMessage("ADDRESS is" + address); 
    LSWebClient client = new LSWebClient(); 
    client.Timeout = 600000; 

    WriteLogMessage("TIMEOUT (client.Timeout) is " + client.Timeout.ToString()); 
    client.Credentials = new NetworkCredential(XYZConfigurationSettings.APIUserName, XYZConfigurationSettings.APIPassword); 

    try { 
     String result = client.DownloadString(address); 
     WriteLogMessage("End Process. RESULT length is " + (result != null ? result.Length : 0)); 
     context.Response.Write(result); 
    } 
    catch (Exception ex) 
    { 
     WriteLogMessage("EXCEPTION!!! Message----" + ex.Message + "---- StackTrace ----" + ex.StackTrace + ""); 
    } 
} 

private bool validateCertificate(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error) 
{ 
    WriteLogMessage("bypassAllCertificateStuff"); 
    return true; 
} 

所以,蹩脚的代码以外,我们在这里放了几件事,试图绕过我们想什么是SSL证书问题。 (将请求超时设置为10分钟,使用自定义证书验证等)。但是,这似乎没有解决这个问题。

下面是我们记录的结果:

2/28/2011 3:35:28 PM: Start 
2/28/2011 3:35:28 PM: Start Process 
2/28/2011 3:35:28 PM: ADDRESS ishttps://<host>/ws/rs/v1/taxonomy/TA/root/ 
2/28/2011 3:35:28 PM: TIMEOUT (client.Timeout) is 600000 
2/28/2011 3:35:50 PM: CheckValidationResult 
2/28/2011 3:35:50 PM: bypassAllCertificateStuff 
2/28/2011 3:41:51 PM: EXCEPTION!!! Message ----Thread was being aborted.---- StackTrace ---- at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest) 
    at System.Net.Connection.CompleteStartRequest(Boolean onSubmitThread, HttpWebRequest request, TriState needReConnect) 
    at System.Net.Connection.SubmitRequest(HttpWebRequest request) 
    at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName) 
    at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint) 
    at System.Net.HttpWebRequest.GetResponse() 
    at System.Net.WebClient.GetWebResponse(WebRequest request) 
    at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream, CompletionDelegate completionDelegate, AsyncOperation asyncOp) 
    at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request) 
    at System.Net.WebClient.DownloadString(Uri address) 
    at System.Net.WebClient.DownloadString(String address) 
    at XYZ.DAO.Handlers.RestServiceHandler.Process(HttpContext context, String url, String restParam) 
    at XYZ.DAO.Handlers.RestServiceHandler.ProcessRequest(HttpContext context)---- 

我试图用我的浏览器来查看返回数据,但浏览器IE6是,它不支持SSL。但是,我可以看到(在Fiddler/Charles代理中)它确实尝试发出请求并收到401错误,但由于无法使用这些程序查看服务器流量,所以无法确切知道错误发生的步骤。

更糟糕的是,我无法在任何其他服务器上重现此问题(注意:它们都是Windows 2008服务器)。

因此,简言之,这里就是我发现:

SOAP - 工作
REST - 没有工作

的Win2008 - 工作
Win2003的 - 没有工作

HTTP - 工作
HTTPS - 无法工作

如果任何人有任何见解或任何其他调试/信息收集,我还没有尝试我会非常伟大。

回答

0

我发现是什么原因导致了Web服务调用挂 - 问题是,我们是用重放攻击保护,以及消化调用该服务的安全性:

  1. 我们的服务器就送一个初始的 请求无安全头
  2. 该请求被回应与一个 标准401挑战提供一个 nonce使用。 (即现时的 攻击后到期 10秒后)
  3. 我们的服务器,然后花了30秒, 使用 这个随机数
  4. 所以服务器仍然后找到 过期现时和再次发出 产生第二响应另一个401挑战。

该循环将持续到本地服务器的线程终止。但是,为什么我们的本地服务器正在花费30美元@#%!生成安全头的秒数超出了我的范围。我检查了通过上述诊断提供的日志,但没有任何帮助。我要把它记录下来,因为服务器超负荷,没有足够的内存来处理它从湿纸袋里走出来。

2

如果将以下内容添加到客户端.config文件中,您应该可以获得更多的跟踪信息。

<system.diagnostics> 
    <sources> 
     <source name="System.Net" switchValue="Information, ActivityTracing"> 
      <listeners> 
       <add name="System.Net" 
        type="System.Diagnostics.TextWriterTraceListener" 
        initializeData="System.Net.trace.log" /> 
      </listeners> 
     </source> 
    </sources> 
</system.diagnostics>