调试失败的 HTTPS WebRequest

Posted

技术标签:

【中文标题】调试失败的 HTTPS WebRequest【英文标题】:Debugging failing HTTPS WebRequest 【发布时间】:2011-08-24 02:01:15 【问题描述】:

我正在编写一个小程序,它将使用 HTTPS 和 HttpWebRequest 类向服务器发出 GET 请求。服务器(显然)具有服务器证书。它还希望客户端提供证书。

但是,在发出请求时,我收到 System.Net.WebException,指出无法建立安全的 TLS/SSL 连接。我很快发现服务器的证书无效。假设这是导致异常的原因,我尝试使用以下代码接受无效证书(不幸的是,更新证书不是一种选择):

ServicePointManager.ServerCertificateValidationCallback += delegate 
    return true;
;

然而,这并没有解决问题。

由于异常没有提供任何细节,因此很难确定是什么原因造成的。我尝试覆盖无效的服务器证书是否不起作用?我提供的客户端证书是否不受服务器信任?我没有以正确的方式加载客户端证书吗?

我很想知道如何调试这类问题的提示。很遗憾,我无权访问服务器或其日志。

下面是代码的重要部分:

ServicePointManager.ServerCertificateValidationCallback += delegate 
    return true;
;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); // url is an HTTPS URL.
X509Certificate clientCert = new X509Certificate("certificate.crt", "password");
req.ClientCertificates.Add(clientCert);
WebResponse resp = req.GetResponse(); // This fails!

【问题讨论】:

FWIW,您可以尝试在使用您的应用程序时运行 Fiddler (www.fiddler2.com)。在这种情况下,Fiddler 往往会显示更具描述性的错误消息。 【参考方案1】:

对其进行一些跟踪!在调试这些东西时,跟踪是你最好的朋友。我曾经有一个客户端无法连接到我们启用 SSL 的服务。使用跟踪我发现有人将系统时钟移到了我们的证书到期日期之后。但我离题了。

启用所有适用的跟踪源并查看日志中是否出现有趣的内容。

Durgaprasad Gorti 有一个旧的(2005 年)但 excellent post,你应该看看。它会准确地向您显示要添加的源,并且在其中他还使用自定义验证回调显示了一些 SSL 跟踪。

来自同一篇博文的 app.config 示例:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.Net">
        <listeners>
          <add name="MyTraceFile"/>
        </listeners>
      </source>
    </sources>

    <sharedListeners>
      <add
      name="MyTraceFile"
      type="System.Diagnostics.TextWriterTraceListener"
      initializeData="System.Net.trace.log"
    />
    </sharedListeners>

    <switches>
      <add name="System.Net" value="Verbose" />
    </switches>

  </system.diagnostics>
</configuration>

希望这将为您提供更多数据。

【讨论】:

【参考方案2】:

一些想法:

    TLS 定义了一些错误代码和警报。 SSL/TLS 库通常在引发异常时提供此代码。也许你能在服务器日志中找到这些信息。

    服务器发送其证书链时可能缺少一些证书。例如,如果服务器仅发送其证书,则客户端可能无法将此证书附加到根证书(如果有一些中间 CA 证书)。

    如果客户端希望使用证书进行身份验证,则服务器应该发送接受的根证书的名称。我的前一点在这里也有效,如果缺少某些中间证书,则无法在其证书和服务器发送的根之间建立链。客户端找不到合适的证书(因为私钥不可用)是另一个可能的问题。

【讨论】:

Jcs:第 3 点很可能是我的问题(我还没有机会看到痕迹告诉我什么)。我将如何解决这个问题?如何添加 SSL 堆栈将检查的根证书? 客户端认证 CA 的配置方式肯定取决于服务器应用程序,或者至少取决于处理 SSL/TLS 的模块。【参考方案3】:

我同意上述 Markus 的解决方案。我曾经遇到过类似的问题,我发现最好的办法是在调试器下获取该异常。

如果您可以在本地运行构建并在调试器中查看该异常,那么您必须深入了解问题的真正实质。

在我正在考虑的情况下,我必须查看 4 或 5 个 innerExceptions,然后才能看到具体告诉我出了什么问题的消息。

我发现这在 .Net 中的许多情况下通常是正确的——你会得到一个带有非常通用的错误消息的异常,并且你需要在深入了解之前降低几个“innerException”级别问题。

希望这会有所帮助。

【讨论】:

以上是关于调试失败的 HTTPS WebRequest的主要内容,如果未能解决你的问题,请参考以下文章

如何在CDSW上调试失败或卡住的Spark应用

dotnet 调试应用启动闪退的方法

用http请求一直失败,用https开头就ok了

从发布模式更改为调试模式时出现“调试断言失败”错误

writeToFile 失败 - 我如何调试它为啥失败(啥工具)?

调试 PhantomJS 网页.打开失败