使用 HttpClient 检查服务器证书

Posted

技术标签:

【中文标题】使用 HttpClient 检查服务器证书【英文标题】:Inspect server certificate using HttpClient 【发布时间】:2017-07-14 06:12:57 【问题描述】:

我正在 WinForms 中重写一些 Web 处理代码,并从 HttpWebRequest 切换到 HttpClient。我要求的最后一件事我似乎不知道如何完成。

在 HttpWebRequest 中,我可以从我正在连接的 Web 服务器捕获证书并显示它:

...
HttpWebRequest request = CreateHttpRequest(destUri);

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

cert = request.ServicePoint.Certificate;

if (cert != null) 
 
  cert2 = new X509Certificate2(cert); 
  X509Certificate2UI.DisplayCertificate(cert2);

...

我找不到使用 HttpClient 捕获证书的等效方法:

//... Use HttpClient.
using (HttpClient client = new HttpClient())

  using (HttpResponseMessage response = await client.GetAsync(destUri))
  
    using (HttpContent content = response.Content)
    
      string result = await content.ReadAsStringAsync();
    
  

我如何/在哪里可以做到这一点?我不知道如何访问 ServicePoint.Certificate。

【问题讨论】:

【参考方案1】:

显然,您不需要从 ServicePointManager.ServerCertificateValidationCallback 获取证书。您可以从 ServicepointManager 本身找到它,如下所示:

//... Use HttpClient.
using (HttpClient client = new HttpClient())

  using (HttpResponseMessage response = await client.GetAsync(destUri))
  
    // Get Certificate Here
    var cert = ServicePointManager.FindServicePoint(destUri).Certificate;
    //
    using (HttpContent content = response.Content)
    
      string result = await content.ReadAsStringAsync();
    
  

【讨论】:

这似乎对我不起作用。证书始终为空。 请注意,这不适用于 .NET Core:github.com/dotnet/runtime/issues/29301【参考方案2】:

建立在 Remus 的答案上 - 这是我在 LinqPad 中拼凑出来的东西,它确实可以让您访问您的证书:

var handler = new WebRequestHandler();
handler.UseDefaultCredentials = true;
handler.AllowPipelining = true;
handler.ServerCertificateValidationCallback =  (sender, cert, chain, error) => 
    //do something with cert here
    cert.Subject.Dump();
    //useless validation on my part
    return true;
;


using (HttpClient client = new HttpClient(handler))

  using (HttpResponseMessage response = await client.GetAsync("https://google.com"))
  
    using (HttpContent content = response.Content)
    
        //foo
    
  

Dump() 输出如下:

CN=*.google.com、O=Google Inc、L=Mountain View、S=California、C=US

CN=www.google.de、O=Google Inc、L=Mountain View、S=加利福尼亚、C=US

CN=www.google.com、O=Google Inc、L=Mountain View、S=加利福尼亚、C=US

【讨论】:

越来越近了。我不明白如何从回调中返回证书本身,以便我可以存储和使用它。我以前可以通过 cert=request.ServicePoint.Certificate;但在回调中这样做让我望而却步。 System.Net.Http.WebRequestHandler 在 .NET Core 中似乎不可用,即使在 .NET 5.0 中也是如此。【参考方案3】:

使用WebRequestHandler 和正确的certificate validation callback。例如,请参阅HttpClient, HttpClientHandler, and WebRequestHandler Explained。

【讨论】:

谢谢。我实际上有一个 HttpClientHandler ,但我没有显示,也没有意识到有一个 WebRequestHandler 扩展。当我尝试使用它时,没有参考。显然您必须手动添加 System.Net.Http.WebRequest 引用,而不仅仅是 using 语句。

以上是关于使用 HttpClient 检查服务器证书的主要内容,如果未能解决你的问题,请参考以下文章

使用 HttpClient 的“远程证书根据验证程序无效”

Https获取服务器证书

SSL证书常见错误和解决办法

SSL,SSL证书,SSL协议,三个其实都是一个吗?还是说有区别呢

HttpClient 无法忽略或绕过自签名证书错误

C# HttpClient 是不是忽略 SSL 证书错误?