C#、.Net Core 私钥认证httpClient

C#, .Net Core Private key authentication httpClient

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

    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;

注释行是我们尝试做的事情的变体。
我们不知道我们还应该尝试什么来处理这个问题。
任何指南都将非常受欢迎

编辑:
我已经尝试在 startup class 中注册它,但它似乎无法正常工作。我总是让证书中的私钥字段为空。并将 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 上。

我认为您没有根据 Named Clients 的文档正确实例化客户端。

您需要在 run-time 中接收 IHttpClientFactory 并像这样请求您的命名客户端:

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

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

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

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