【问题标题】:Ignore bad certificate - .NET CORE忽略错误的证书 - .NET CORE
【发布时间】:2017-07-31 11:18:32
【问题描述】:

我正在编写一个 .NET Core 应用程序来轮询远程服务器并传输显示的数据。这在 PHP 中运行良好,因为 PHP 忽略了证书(这在浏览器中也是一个问题),但我们希望将其移至 C# .NET CORE,因为这是系统中唯一剩下的 PHP。

我们知道服务器很好,但由于各种原因,证书无法/不会很快更新。

请求正在使用 HttpClient:

        HttpClient httpClient = new HttpClient();
        try
        {
            string url = "https://URLGoesHere.php";
            MyData md = new MyData();  // this is some data we need to pass as a json
            string postBody = JsonConvert.SerializeObject(md);
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                
            HttpResponseMessage wcfResponse = await httpClient.PostAsync(url, new StringContent(postBody, Encoding.UTF8, "application/json"));
            Console.WriteLine(wcfResponse.Content);
        }
        catch (HttpRequestException hre)
        {
        // This exception is being triggered
        }

对此进行研究后,似乎普遍建议使用 ServicePointManager,但这在 .NET Core 中不可用,我无法找到推荐的替代品。

在 .NET Core 中是否有一种简单或更好的方法来做到这一点?

【问题讨论】:

  • 这可能会有所帮助stackoverflow.com/questions/2675133/…
  • 感谢所有指向其他线程的指针-但过去访问过所有线程我仍然遇到问题-它们都不会编译。每次都有一些参考资料找不到。显然我在这里遗漏了一些明显的东西!小的 sn-ps 没有提供足够的信息(对我来说),比如需要包含或引用的其他内容。 Ctrl-。也没有提出合理的建议。
  • 您应该修复证书错误,而不是忽略证书错误。否则根本不需要证书。
  • 当然,我 100% 同意你的意见,并且我已经提出了要求,但是服务器不在我的控制之下,也不归我的公司所有,它位于很远的数据中心,我被什么困住了我们有。这是一个很快就会过时的遗留系统,负责维护的人说修复证书不会发生。我的任务是迁移现有数据并捕获新数据,直到它被替换。

标签: c# .net-core ssl-certificate


【解决方案1】:

你想要类似的东西而不是new HttpClient()

var handler = new System.Net.Http.HttpClientHandler();
using (var httpClient = new System.Net.Http.HttpClient(handler))
{
    handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
    {
        // Log it, then use the same answer it would have had if we didn't make a callback.
        Console.WriteLine(cert);
        return errors == SslPolicyErrors.None;
    };

    ...
}

这应该可以在 Windows 和 Linux 上运行,其中 libcurl 被编译为使用 openssl。使用其他 curl 后端,Linux 会抛出异常。

【讨论】:

  • 仅供参考,它也不适用于 Mac OS 上的 .NET Core 1.1。异常消息为:The libcurl library in use (7.51.0) and its SSL backend ("SecureTransport") do not support custom handling of certificates. A libcurl built with OpenSSL is required.)
  • Ricky,请参阅我上面的答案以了解几个选项。
  • @bartonjs:感谢您为我指明了正确的方向,让我弄清楚如何在 macos 和可能的某些 Linux 版本上的所有场景中使用它。这很有帮助。
  • 这个答案对我有用。请注意,如果您使用 'cert.GetPublicKeyString();'为了与您预期的证书进行比较,您可以将其转换为证书固定owasp.org/index.php/Certificate_and_Public_Key_Pinning 的一种形式,以增强安全性(或至少确保您不会降级它)。
  • @ChrisHalcrow 据我所知,没有这种机制(不像 ServicePoint,甚至不是“全局”)
【解决方案2】:

让 Linux 和 macOS 工作

如果您在 Linux 或 macOS 中工作,您可能会遇到HttpClient 不允许您访问自签名证书的情况,即使它位于您的受信任的商店中。您可能会得到以下信息:

System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates environment variable

如果您正在实施(如其他答案所示)

handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
{
    // Log it, then use the same answer it would have had if we didn't make a callback.
    Console.WriteLine(cert);
    return errors == SslPolicyErrors.None;
};

这是由于机器上的 libcurl 版本不支持 .Net Core 收集适当数据以调用 ServerCertificateCustomValidationCallback 所需的适当回调。例如,框架无法创建cert 对象或另一个参数。更多信息可以在 dotnet core 的 github 存储库中的 .NET Core 中提供的解决方法的讨论中找到:

https://github.com/dotnet/corefx/issues/19709

解决方法(仅应用于测试或特定的内部应用程序)如下:

using System;
using System.Net.Http;
using System.Runtime.InteropServices;

namespace netcurl
{
    class Program
    {
        static void Main(string[] args)
        {
            var url = "https://localhost:5001/.well-known/openid-configuration";
            var handler = new HttpClientHandler();
            using (var httpClient = new HttpClient(handler))
            {
                // Only do this for testing and potentially on linux/mac machines
                if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && IsTestUrl(url))
                {
                    handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
                }

                var output = httpClient.GetStringAsync(url).Result;

                Console.WriteLine(output);
            }
        }

        static  bool IsTestUrl(string url) => url.Contains("localhost");
    }
}

还有另一种方法可以解决这个问题,那就是使用带有 openssl 支持的 libcurl 版本。对于 macOS,这是一个很好的教程:

https://spin.atomicobject.com/2017/09/28/net-core-osx-libcurl-openssl/

对于短版本,获取最新的 libcurl 的副本,该版本使用 openssl 支持编译:

brew install curl --with-openssl

您可能不想强制整个操作系统使用非 Apple 版本的 libcurl,因此您可能希望使用 DYLD_LIBRARY_PATH 环境变量而不是使用 brew 强制将二进制文件链接到常规操作系统的路径。

export DYLD_LIBRARY_PATH=/usr/local/opt/curl/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}

在终端中运行dotnet 时,可以使用上述命令设置适当的环境变量。不过,这并不真正适用于 GUI 应用程序。如果您使用的是 Visual Studio for Mac,则可以在项目运行设置中设置环境变量:

当我使用 IdentityServer4 和令牌授权时,第二种方法对我来说是必要的。 .NET Core 2.0 授权管道正在使用 HttpClient 实例调用令牌授权。由于我无权访问HttpClient 或其HttpClientHandler 对象,因此我需要强制HttpClient 实例使用适当版本的libcurl,该版本将查看我的KeyChain 系统根目录以获得我的受信任证书。否则,在尝试使用 Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)] 属性保护 webapi 端点时,我会得到 System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates environment variable

在找到解决方法之前,我花了几个小时研究这个问题。我的整个目标是在使用 IdentityServer4 的 macOS 开发过程中使用自签名证书来保护我的 webapi。希望这会有所帮助。

【讨论】:

  • 非常感谢您的帖子。它帮助我朝着正确的方向前进。我们使用的是 .NET Standard 2.0,所以首先我不明白为什么我会遇到所有这些问题......我已经尝试了 curl 和 openssl 之类的一切,没有任何帮助。所以我做了一个讨厌的黑客(不能让你的代码示例也不能工作)。 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { handler.ServerCertificateCustomValidationCallback = null; }
  • 仅供参考,在这也花了很多时间之后,我从 .NET core 2.0 更新到 .NET core 2.1,我的自签名证书问题消失了。我认为这与他们添加的新 SocketsHandler 有关,但我不确定。因此,使用 HttpClient 从 IdentityServer4 获取身份令牌和提供的 Nuget 包现在都可以工作了。
【解决方案3】:

//在启动配置服务时添加如下代码

services.AddHttpClient(settings.HttpClientName, client => {
// code to configure headers etc..
}).ConfigurePrimaryHttpMessageHandler(() => {
                  var handler = new HttpClientHandler();
                  if (hostingEnvironment.IsDevelopment())
                  {
                      handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
                  }
                  return handler;
              });

现在您可以在服务中使用 IHttpClientFactory CreateClient 方法

【讨论】:

    【解决方案4】:

    只是为了添加另一个变体,您可以添加指纹并在回调中检查它以使事情更安全,例如:

    if (!string.IsNullOrEmpty(adminConfiguration.DevIdentityServerCertThumbprint))
    {
       options.BackchannelHttpHandler = new HttpClientHandler
       {
          ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => certificate.Thumbprint.Equals(adminConfiguration.DevIdentityServerCertThumbprint, StringComparison.InvariantCultureIgnoreCase)
       };
    }
    

    adminConfiguration.DevIdentityServerCertThumbprint 是您将使用自签名证书的指纹设置的配置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-05
      • 2018-11-10
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 2023-03-23
      相关资源
      最近更新 更多