【问题标题】:C#, .Net Core Private key authentication httpClientC#, .Net Core 私钥认证 httpClient
【发布时间】:2019-06-06 14:55:34
【问题描述】:

我们的朋友在将私有证书加载到 httpHandler 时遇到问题。
我们正在使用 .net 核心,需要在云中托管所有应用程序。
主要目标是从 SQS 获取消息并在使用数据后执行一些指定的 API 拍摄。
我们的公钥/私钥证书有问题。我们已经尝试了所有可能的加载方式。

    public async Task<HttpResponseMessage> VisitHttps()
    {
        // Proceed for an invalid cerficate
        ServicePointManager.ServerCertificateValidationCallback +=
        (sender, certificate, chain, sslPolicyErrors) => true;

        // Add the certificate
        var handler = new HttpClientHandler();
        var cert = GetMyCert();
        if (cert != null)
        {
            handler.ClientCertificates.Add(cert);
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
            //handler.PreAuthenticate = true;
        }
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;


        HttpClient cclient = new HttpClient(handler)
        {
            //BaseAddress = new Uri("https://someurl.com")

        };
        cclient.DefaultRequestHeaders.Accept.Clear();
        cclient.DefaultRequestHeaders.Accept.Add(new 

MediaTypeWithQualityHeaderValue("application/json"));
            return await cclient.GetAsync("https://some-url.com/ping"); }

GetMyCert() 方法如下所示:

string currentLocation = $"{AppDomain.CurrentDomain.BaseDirectory}key-public.crt";
                //var xcert = new X509Certificate2(currentLocation, "password");

                ////var currentLocationPriv = $"{AppDomain.CurrentDomain.BaseDirectory}key-private.crt";
                ////var privcert = new X509Certificate2(currentLocationPriv, "password", X509KeyStorageFlags.EphemeralKeySet);
                //var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                //certStore.Open(OpenFlags.ReadWrite);
                //certStore.Add(xcert);
                //certStore.Close();
            //return xcert;

            X509Store store = new X509Store("My", StoreLocation.CurrentUser);
            X509Certificate2 cert;
            cert = new X509Certificate2(File.ReadAllBytes(currentLocation), "password", X509KeyStorageFlags.MachineKeySet);
            bool result = cert.Verify();
            var r2 = result;
            return cert;

注释行与我们尝试做的不同。
我们不知道还应该尝试什么来处理这个问题。
任何指导方针都会受到欢迎

编辑:
我已经尝试在启动类中注册它,但它似乎无论如何都不起作用。我总是将证书内的私钥字段为空。并将 hasPrivateKey 标记为 false。

 private void CreateCert(IServiceCollection services)
    {
        string currentLocation = $"{AppDomain.CurrentDomain.BaseDirectory}key-public.crt";
        var certificate = new X509Certificate2(currentLocation, "password");
        services.AddHttpClient("TestClient", client =>
        {
            client.BaseAddress = new Uri("https://someurl.com");
        })
        .ConfigurePrimaryHttpMessageHandler(() =>
            {
            var handler = new HttpClientHandler();
            handler.ClientCertificates.Add(certificate);
            return handler;
        });
    }  

我的测试代码:

        [Fact]
    public async Task ShouldPong()
    {
        var testClient = new TestClient()
        {
            BaseAddress = new Uri("https://someurl.com")
        };
        var result = await testClient.GetAsync("/ping");
        result.StatusCode.Should().Be(HttpStatusCode.OK);
    }

测试客户端:

public class TestClient : HttpClient
{
    public TestClient()
        :base()
    {

    }

    public TestClient(HttpMessageHandler handler)
        : base(handler)
    {

    }
}  

编辑:
将 .crt 文件更改为 .pfx 文件时问题已解决。由于我们使用的 API 托管在 nginx 上。

【问题讨论】:

  • .Net Core 提供了一种处理 HttpClient 的新方法,即通过注入 HttpClientFactory。还有命名客户端,即注入到您的模块/类中的预配置客户端。可能,您可以使用这个问题的答案:stackoverflow.com/questions/56480160/…
  • 对不起,你已经链接了我自己的问题,我会检查 httpClientFactory :)
  • 对不起,我错了哈哈。这是正确的链接:stackoverflow.com/questions/52371768/…
  • 好的,谢谢 :) 这没有帮助,顺便说一句,问题可能是当我在调试期间查看句柄时,它显示私钥为空且未设置。我应该用我的公钥以某种方式加载它还是添加它?

标签: c# .net public-key-encryption private-key


【解决方案1】:

已通过创建 .PFX 文件解决了该问题。我们访问的服务器托管在需要 .pfx 格式的 nginx 上。 .crt 文件是对 nginx 无效的 PEM 证书。

【讨论】:

  • 是的解决方案正确,但你应该知道 nginx 的 PEM 格式在 linux 环境中使用也是正确的
  • 好吧,所以我不知道为什么这在使用 .crt 文件时不起作用,而当我将它们组合成 .pfx 证书文件时起作用。我认为 nginx 只是不支持 PEM 格式:P。我在 windows 和 mac 上测试它。
  • 如果您尝试使用 digitalocean 进行锻炼,那么您会看到它默认使用 PEM。证书格式中与 nginx 没有关系。 Nginx 看起来 2 东西是 ssl 的正确键
【解决方案2】:

我认为您没有正确地实例化客户端,因此使用Named Clients 的文档。

您需要在运行时接收 IHttpClientFactory 并要求您的命名客户端,如下所示:

 var client = _clientFactory.CreateClient("TestClient");

关于使用依赖注入进行测试,我相信这篇微软教程可以提供帮助:Integration Tests Asp.Net Core。这里的交易是,由于 Startup.cs 文件和核心依赖注入器是框架的一部分,您需要在测试上下文中设置模拟 Web 应用程序。微软为此提供了 WebApplicationFactory。

This 示例演示了在模拟 Web 应用程序环境中使用由 IHttpClientFactory 提供的 httpClient 进行的测试。

【讨论】:

  • 我已经按照你说的做了。注册如上。并试图从邮递员那里 ping 我的操作来测试它。我已经在构造函数中注入了 IHttpClientFactory ,然后按照你所说的创建了客户端。尝试使用 GetAsync 方法访问端点,但仍然得到相同的响应。未经授权。我也应该在某处注册私钥吗? (我有 2 个 .cert 文件,1 个 public.cert 和 1 个 private.cert)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
相关资源
最近更新 更多